package com.codi.bus.core.service.impl;

import com.codi.base.util.*;
import com.codi.bus.constant.GlobalConstant;
import com.codi.bus.constant.RuleConstant;
import com.codi.bus.core.dao.*;
import com.codi.bus.core.domain.*;
import com.codi.bus.core.resultModel.*;
import com.codi.bus.core.service.*;
import com.codi.bus.core.service.model.*;
import com.codi.bus.core.service.util.AssetsQueryUtils;
import com.codi.bus.core.service.util.CalculateAssetsUtils;
import com.codi.bus.core.service.util.HundsunUtils;
import com.codi.bus.core.service.util.ModelPopulateUtils;
import com.codi.bus.exception.BaseException;
import com.codi.bus.exception.SystemDBException;
import com.codi.fcloud.ufx.constant.HSOutputParameterNames;
import com.codi.fcloud.ufx.hssale.query.AccountBankQuery;
import com.codi.message.constant.ErrorConstant;
import com.codi.trade.dto.*;
import com.codi.trade.response.HsAccoBankQueryResponse;
import com.codi.trade.response.HsFundDividendQryResponse;
import com.codi.trade.service.*;
import com.codi.trade.service.portfolio.HsCombIncomeQryService;
import com.codi.trade.service.portfolio.HsCombSharesQryService;
import com.codi.trade.service.portfolio.HsPortfolioQryService;
import com.codi.trade.service.portfolio.HsShareDetailQryService;
import com.google.common.base.Strings;
import org.apache.commons.collections.map.HashedMap;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;

/**
 * Created by asus on 2018/3/9.
 */
@Transactional
@Service("assetsQueryService")
public class AssetsQueryServiceImpl implements AssetsQueryService {
    private static final Logger logger = LoggerFactory.getLogger(AssetsQueryServiceImpl.class);

    @Resource(name = "userDao")
    private UserDao userDao;

    @Resource(name = "tradeConfirmQueryService")
    private TradeConfirmQueryService tradeConfirmQueryService;

    @Resource(name = "shareQueryService")
    private ShareQueryService shareQueryService;

    @Resource(name = "userBankDao")
    private UserBankDao userBankDao;

    @Resource(name = "tradeApplyQueryService")
    private TradeApplyQueryService tradeApplyQueryService;

    @Resource(name = "fundDetailService")
    private FundDetailService fundDetailService;

    @Resource(name = "lookupDao")
    private LookupDao lookupDao;

    @Resource(name = "workingDateService")
    private WorkingDateService workingDateService;

    @Resource(name = "dividendsQueryService")
    private DividendsQueryService dividendsQueryService;

    @Autowired
    private HsPortfolioQryService portfolioQryService;

    @Autowired
    private HsShareDetailQryService hsShareDetailQryService;

    @Autowired
    private PortfolioService portfolioService;

    @Autowired
    private HsCombSharesQryService hsCombSharesQryService;

    @Autowired
    private HsCombIncomeQryService hsCombIncomeQryService;

    @Autowired
    private IncomeQueryService incomeQueryService;

    @Autowired
    private UserService userService;

    @Autowired
    private AccountBankQuery accountBankQuery;

    @Autowired
    private BankService bankService;

    @Autowired
    private QueryService queryService;

    @Autowired
    private FundCombinationService fundCombinationService;

    @Autowired
    private UserAssetsDao userAssetsDao;

    @Autowired
    private FundAssetsDao fundAssetsDao;

    @Autowired
    private OneFundDao oneFundDao;

    @Autowired
    private OnePortfolioDao onePortfolioDao;

    @Autowired
    private OneWalletDao oneWalletDao;

    @Autowired
    private PortfolioAssetsDao portfolioAssetsDao;

    @Autowired
    private PortfolioFundDao portfolioFundDao;

    @Autowired
    private PortfolioFundTradeDao portfolioFundTradeDao;

    @Autowired
    private FundCombinationDao fundCombinationDao;

    @Autowired
    private PortfolioTradeDao portfolioTradeDao;

    @Autowired
    private WalletAssetsDao walletAssetsDao;

    @Autowired
    private ProfitDao profitDao;

    @Autowired
    private InsidePortfolioDao insidePortfolioDao;

    @Autowired
    private InsidePortfolioAssetsDao insidePortfolioAssetsDao;

    @Autowired
    private PortfolioTradeAccoDao portfolioTradeAccoDao;

    @Autowired
    private FundDividentsDao fundDividentsDao;
    @Autowired
    private DividendApplyService dividendApplyService;

    public static Date getZeroTime() {
        Calendar c = Calendar.getInstance();            //得到当前日期和时间
        c.set(Calendar.HOUR, 0);                        //把当前时间小时变成０
        c.set(Calendar.MINUTE, 0);                      //把当前时间分钟变成０
        c.set(Calendar.SECOND, 0);                      //把当前时间秒数变成０
        c.set(Calendar.MILLISECOND, 0);                 //把当前时间毫秒变成０
        Date date1 = c.getTime();
        return date1;
    }

    /**
     * 初始化分红记录
     * @param user
     */
    @Override
    public void initDividents(User user) {

        DividendApplyResult result = new DividendApplyResult();
        // populate
        List<DividendModel> dividendModelList;

        // 组合 分红交易记录
        HsDividendQryDto hsDividendQryDto = HsDividendQryDto.builder()
            .client_id(user.getExternalClientId())
            .sort_direction("1")
            .qry_beginrownum(1)
            .reqry_recordsum_flag("1")
            .request_num(GlobalConstant.MAX_REQUEST_NUM)
            .build();

        Map<String, Object> map = dividendsQueryService.queryDto(hsDividendQryDto);
        List<Map<String, Object>> list = new ArrayList<>();
        // 查询结果
        HundsunUtils.ConvertToList(map, list, result);
        if (!result.getSuccess()) {
            // 送你一手异常
        }
        // populate
        dividendModelList = ModelPopulateUtils.populateDividend(list, result);
        addDividend(dividendModelList,user);

    }

    /**
     * 添加分红记录
     *
     * @param dividendModelList
     * @param user
     */
    private void addDividend(List<DividendModel> dividendModelList, User user) {
        for (DividendModel dividendModel : dividendModelList) {
            if (!"1".equals(dividendModel.getAutoBuy())) {
                continue;
            }
            FundDividents fundDivident = new FundDividents();
            fundDivident.setUserId(Math.toIntExact(user.getUserId()));
            fundDivident.setClientId(user.getExternalClientId());
            fundDivident.setAffirmDate(dividendModel.getAffirmDate());
            fundDivident.setTaAcco(dividendModel.getTaAccount());
            fundDivident.setTradeAcco(dividendModel.getTradeAccount());
            fundDivident.setAutoBuy(dividendModel.getAutoBuy());
            fundDivident.setDividendBala(dividendModel.getDividendBalance());
            fundDivident.setDividendDate(dividendModel.getDividendDate());
            fundDivident.setDividendShare(dividendModel.getDividendShare());
            fundDivident.setDividendTotalbala(dividendModel.getTotalDividendBalance());
            fundDivident.setEquityRegDate(dividendModel.getEquityRegDate());
            fundDivident.setFrozenBala(dividendModel.getFrozenBala());
            fundDivident.setFrozenShares(dividendModel.getFrozenShares());
            fundDivident.setFundCode(dividendModel.getFundCode());
            fundDivident.setNetValue(dividendModel.getNetValue());
            fundDivident.setRegShare(dividendModel.getDividendShare());
            fundDivident.setUnitBala(dividendModel.getUnitBala());
            fundDivident.setUnitShare(dividendModel.getUnitShare());
            fundDivident.setTaSerialId(dividendModel.getTaSerialId());
            // 当日确认份额
            fundDivident.setTodayConfirmShare(null);
            fundDividentsDao.insert(fundDivident);
        }
    }

    @Override
    public AssetsResult queryAssets(Long userId) throws BaseException {
        try {

            /**
             * Step 0: 验证数据
             */
            // 结果
            AssetsResult result = new AssetsResult();
            // 获取 交易账号
            List<UserBank> userBankList = userBankDao.getListByUserId(userId);
            // 获取用户
            User user = userDao.getEntity(userId);

            // 判断是否已开户
            if (user == null || StringUtil.isEmpty(user.getExternalClientId())) {
                result.setSuccess(false);
                result.setErrorCode(ErrorConstant.ERROR_NO_ACCOUNT);
                result.setErrorType(GlobalConstant.ERROR_TYPE_APPLICATION);
                return result;
            }
            // 获取T+0基金
            List<Lookup> lookups = lookupDao.getLookupByType(RuleConstant.RULE_LOOKUP_TYPE_T0FUND);

            /**
             * Step 0-1:查询当前工作日
             */
            Date currentWorkingDate = workingDateService.getWorkingDay(new Date());
            // 根据恒生银行编号获取银行名称
            List<Lookup> banklookups = lookupDao.getLookupByType(RuleConstant.RULE_LOOKUP_TYPE_HSBANK);
            /**
             * Step 1: 资产查询
             */
            // 查询该用户下的所有份额
            HsShareQueryDto hsShareQueryDto = HsShareQueryDto.builder()
                .request_num(GlobalConstant.MAX_REQUEST_NUM)
                .reqry_recordsum_flag("1")
                .qry_beginrownum(1)
                .sort_direction("1")
                .client_id(user.getExternalClientId())
                .build();
            Map<String, Object> map = shareQueryService.query(hsShareQueryDto);

            // 查询结果
            List<Map<String, Object>> list = new ArrayList<>();
            HundsunUtils.ConvertToList(map, list, result);
            if (!result.getSuccess()) {
                return result;
            }

            // populate
            ShareListResult shareListResult = new ShareListResult();
            List<ShareModel> shares = ModelPopulateUtils.populateShare(list, banklookups, shareListResult);

            //份额明细
            ShareDetailQryDto shareDetailQryDto = ShareDetailQryDto.builder()
                .qry_beginrownum("1")
                .begin_date(DateUtils.formatDate4(new Date()))
                .client_id(user.getExternalClientId())
                .end_date(DateUtils.formatDate4(new Date()))
                .reqry_recordsum_flag("1")
                .request_num(GlobalConstant.MAX_REQUEST_NUM)
                .sort_direction("1")
                .build();
            map = hsShareDetailQryService.query(shareDetailQryDto);
            list = new ArrayList<>();
            HundsunUtils.ConvertToList(map, list, result);
            if (!result.getSuccess()) {
                return result;
            }
            //普通基金
            List<ShareDetailQryModel> shareDetailQryFundModels = new ArrayList<>();
            //组合
            List<ShareDetailQryModel> shareDetailQryPortfolioModels = new ArrayList<>();
            List<String> tradeAccounts = new ArrayList<>();
            if (userBankList != null) {
                if (userBankList.size() != 0) {
                    for (UserBank userBank : userBankList) {
                        //累加普通基金  份额明细
                        shareDetailQryFundModels = ModelPopulateUtils.populateShareDetailQryFund(list, userBank);
                        //将交易账号 合并
                        tradeAccounts.add(userBank.getExternalTradeAccount());
                    }
                }
            }
            shareDetailQryPortfolioModels = ModelPopulateUtils.populateShareDetailQryPorefolio(list, tradeAccounts);

            /**
             * 普通基金份额查询  非组合部分
             */
            Map<String, ShareModel> shareMap = new HashMap<>();
            List<ShareModel> normalShares = new ArrayList<>();
            List<Map<String, Object>> listAll = new ArrayList<>();
            List<Map<String, Object>> listDividend = new ArrayList<>();
            List<Map<String, Object>> listIncome = new ArrayList<>();
            if (userBankList != null) {
                if (userBankList.size() != 0) {
                    for (UserBank userBank : userBankList) {
                        // 查询该用户下的所有非组合基金份额
                        HsShareQueryDto hsShareQueryDtoFund = HsShareQueryDto.builder()
                            .request_num(GlobalConstant.MAX_REQUEST_NUM)
                            .reqry_recordsum_flag("1")
                            .qry_beginrownum(1)
                            .sort_direction("1")
                            .trade_acco(userBank.getExternalTradeAccount())
                            .client_id(user.getExternalClientId())
                            .build();
                        map = shareQueryService.query(hsShareQueryDtoFund);
                        //logger.warn("map：{}", map.get(GlobalConstant.KEY_LIST_MAP));

                        list = new ArrayList<>();
                        HundsunUtils.ConvertToList(map, list, result);
                        if (!result.getSuccess()) {
                            return result;
                        }
                        listAll.addAll(list);

                        // 查询该用户该交易账号下分红
                        HsDividendQryDto hsDividendQryDto = HsDividendQryDto.builder()
                            .request_num(GlobalConstant.MAX_REQUEST_NUM)
                            .reqry_recordsum_flag("1")
                            .qry_beginrownum(1)
                            .sort_direction("1")
                            .trade_acco(userBank.getExternalTradeAccount())
                            .client_id(user.getExternalClientId())
                            .build();
                        map = dividendsQueryService.queryDto(hsDividendQryDto);
                        list = new ArrayList<>();
                        HundsunUtils.ConvertToList(map, list, result);

                        if (!result.getSuccess()) {
                            return result;
                        }
                        listDividend.addAll(list);

                        //测试一下 Income接口
                        HsIncomeQueryDto hsIncomeQueryDto = HsIncomeQueryDto.builder()
                            .end_date(DateUtils.formatDate4(DateUtils.addDay(new Date(), 0)))
                            .begin_date(DateUtils.formatDate4(DateUtils.addDay(new Date(), -3)))
                            .client_id(user.getExternalClientId())
                            .qry_beginrownum(1)
                            .reqry_recordsum_flag("1")
                            .request_num(GlobalConstant.MAX_REQUEST_NUM)
                            .sort_direction("1")
                            .trade_acco(userBank.getExternalTradeAccount())
                            .trade_mode("0")
                            .build();
                        map = incomeQueryService.query(hsIncomeQueryDto);
                        list = new ArrayList<>();
                        HundsunUtils.ConvertToList(map, list, result);
                        if (!result.getSuccess()) {
                            throw new BaseException(result.getErrorCode(), result.getErrorMessage());
                        }
                        for (Map<String, Object> map1 : list) {
                            map1.put(HSOutputParameterNames.TRADE_ACCO, userBank.getExternalTradeAccount());
                        }
                        listIncome.addAll(list);

                    }
                }
            }
            normalShares = ModelPopulateUtils.populateNormalShare(listAll, banklookups);
            // populate
            BaseListResult baseListResult = new BankListResult();
            List<DividendModel> dividends = ModelPopulateUtils.populateDividend(listDividend, baseListResult);
            List<IncomeModel> incomeModels = ModelPopulateUtils.populateIncome(listIncome);
            List<IncomeModel> incomeModelsWallet = AssetsQueryUtils.getIncomeWallet(incomeModels, lookups);
            List<IncomeModel> incomeModelsNormal = AssetsQueryUtils.getIncomeNormal(incomeModels, lookups);
            /*
            收益这块强调一下   这部分代码还没有加上  全赎部分的累计收益  后面到这块的时候解决一下
             */

            /**
             *  组合份额查询
             */
            CombSharesQryDto combSharesQryDto = CombSharesQryDto.builder()
                .request_num(GlobalConstant.MAX_REQUEST_NUM)
                .reqry_recordsum_flag("1")
                .client_id(user.getExternalClientId())
                .qry_beginrownum("1")
                .build();
            map = hsCombSharesQryService.query(combSharesQryDto);
            list = new ArrayList<>();
            HundsunUtils.ConvertToList(map, list, result);
            if (!result.getSuccess()) {
                return result;
            }
            List<CombSharesQryModel> combSharesQryModels = ModelPopulateUtils.populateCombSharesQry(list);
            //将同一组合的基金放在一起  存入一个map
            Map<String, List<CombSharesQryModel>> combMap = new HashMap<>();
            List<String> combCode = new ArrayList<>();
            Map<String, List<CombSharesQryModel>> combTradeMap = new HashMap<>();
            //按交易账号区分
            portfolioService.getCombTradeMap(combSharesQryModels, combTradeMap);
            portfolioService.getCombMap(combSharesQryModels, combMap, combCode);
            //组合投资查询
            //PortfolioQryDto portfolioQryDto = portfolioQryService.getRequestDto(GlobalConstant.MAX_REQUEST_NUM.toString(), "1", "1", "", "", user.getExternalClientId(), "1");
/**
 * 记得改回来
 */
//            PortfolioQryDto portfolioQryDto = PortfolioQryDto.builder()
//                .request_num(GlobalConstant.MAX_REQUEST_NUM)
//                .reqry_recordsum_flag("1")
//                .sort_direction("1")
//                .client_id(user.getExternalClientId())
//                .qry_beginrownum("1")
//                .build();
//
//            map = portfolioQryService.query(portfolioQryDto);
//            list = new ArrayList<>();
//            HundsunUtils.ConvertToList(map, list, result);
//            if (!result.getSuccess()) {
//                return result;
//            }
//            //将同一组合的基金放在一起  存入一个map
//
//            List<PortfolioQryModel> portfolioQryModels = ModelPopulateUtils.populatePortfolioQry(list);
//            Map<String, List<PortfolioQryModel>> portfolioMap = new HashMap<>();
//            List<String> portfolioCode = new ArrayList<>();
//            //PortfolioQryModelByCode portfolioQryModelByCode = new PortfolioQryModelByCode();
//            portfolioService.getPortfolioMap(portfolioQryModels, portfolioMap, portfolioCode);
            Map<String, List<PortfolioQryModel>> portfolioMap = new HashMap<>();

            // 收益查询  组合    按交易账号查
            Map<String, List<IncomeModel>> mapIncome = new HashMap<>();
            if (combTradeMap.keySet() != null) {
                for (String tradeAccount : combTradeMap.keySet()) {
                    HsIncomeQueryDto hsIncomeQueryDto = HsIncomeQueryDto.builder()
                        .end_date(DateUtils.formatDate4(DateUtils.addDay(new Date(), 0)))
                        .begin_date(DateUtils.formatDate4(DateUtils.addDay(new Date(), -3)))
                        .client_id(user.getExternalClientId())
                        .qry_beginrownum(1)
                        .reqry_recordsum_flag("1")
                        .request_num(GlobalConstant.MAX_REQUEST_NUM)
                        .sort_direction("1")
                        .trade_acco(tradeAccount)
                        .trade_mode("0")
                        .build();
                    map = incomeQueryService.query(hsIncomeQueryDto);
                    list = new ArrayList<>();
                    HundsunUtils.ConvertToList(map, list, result);
                    if (!result.getSuccess()) {
                        throw new BaseException(result.getErrorCode(), result.getErrorMessage());
                    }
                    for (Map<String, Object> map1 : list) {
                        map1.put(HSOutputParameterNames.TRADE_ACCO, tradeAccount);
                    }
                    List<IncomeModel> combIncomeModels = ModelPopulateUtils.populateIncome(list);
                    mapIncome.put(tradeAccount, combIncomeModels);

                }
            }


            /**
             * Step 3: 获取T+0基金以及从聚源获取基金信息
             */

            // 从聚源获取基金信息
            List<String> fundCodeList = new ArrayList<String>();
            for (ShareModel shareModel : shares) {
                fundCodeList.add(shareModel.getFundCode());
            }

            List<FundNetValueResult> fundNetValueList = null;
            boolean gliDataException = false;
            try {
                fundNetValueList = fundDetailService.getFundNetValueByBatch(fundCodeList, DateUtils.addDay(new Date(), -1));
            } catch (Exception ex) {
                ExceptionUtil.logError(logger, "queryAssets - fundDetailService - Exception:", ex);
                gliDataException = true;
            }

            // 如果没有找到聚源的，返回错误
            if (gliDataException || fundNetValueList == null) {
                result.setErrorCode(ErrorConstant.ERROR_GILDATA_WRONG);
                result.setSuccess(false);
                result.setErrorType(GlobalConstant.ERROR_TYPE_SYSTEM);
                return result;
            }

            // 获取上一工作日净值
            Map<String, BigDecimal> lastNetValues = new HashedMap();
            for (FundNetValueResult netValueResult :
                fundNetValueList) {
                if (netValueResult != null) {
                    if (!lastNetValues.containsKey(netValueResult.getFundCode())) {
                        BigDecimal lastUnitValue = getLastUnitValue(netValueResult.getFundCode(), netValueResult.getTradingDay());
                        lastNetValues.put(netValueResult.getFundCode(), lastUnitValue);
                    }
                }
            }


            /**
             * Step 4: 计算出前后15天未确认的快速赎回的份额（如果要精确计算的话，只要算当前工作日以及上一工作日的未T+
             * 1确认的实时成功的快速赎回的份额）
             */
            Date beginDate = DateUtils.addDay(new Date(), GlobalConstant.FAST_REDEEM_INTERVAL_DAYS_AFTER_BEFORE * (-1));
            Date endDate = DateUtils.addDay(new Date(), GlobalConstant.FAST_REDEEM_INTERVAL_DAYS_AFTER_BEFORE);

            ApplyListResult applyListResult = queryApplys(userId, beginDate, endDate,
                GlobalConstant.FUND_BUSIN_CODE_T0_FAST_APPLY_SELL, GlobalConstant.TACONFIRM_FLAG_REAL_SUCCESS,
                true);
            if (!applyListResult.getSuccess()) {
                throw new BaseException(applyListResult.getErrorCode(), applyListResult.getErrorMessage());
            }

            //近期快速赎回的份额
            Map<String, BigDecimal> fastRedeemShares = CalculateAssetsUtils.getFastSellShares(applyListResult.getApplys());

            //当日快速赎回份额
            Map<String, BigDecimal> todayFastRedeemShares = CalculateAssetsUtils.getTodayFastSellShares(applyListResult.getApplys());


            /**
             * Step 5: 计算结果值
             */
            //计算组合份额，资产 日收益
            List<PortfolioModel> portfolioModels = new ArrayList<>();

            //按交易账号 区分开的分红列表
            Map<String, List<DividendModel>> dividendMap = new HashMap<>();
            for (String key : combTradeMap.keySet()) {
                getDividends(key, user, dividendMap);
            }

            //组合收益
            CombIncomeQryDto combIncomeQryDto = CombIncomeQryDto.builder()
                .request_num(GlobalConstant.MAX_REQUEST_NUM)
                .reqry_recordsum_flag("1")
                .sort_direction("1")
                .client_id(user.getExternalClientId())
                .qry_beginrownum("1")
                .build();
            map = hsCombIncomeQryService.query(combIncomeQryDto);
            list = new ArrayList<>();
            HundsunUtils.ConvertToList(map, list, result);
            if (!result.getSuccess()) {
                return result;
            }
            Map<String, CombIncomeQryModel> modelMap = ModelPopulateUtils.populateCombIncomeQry(list);

            for (String code : combCode) {
                if (combMap.get(code) == null) {
                    continue;
                }

                PortfolioModel portfolioModel = new PortfolioModel();
                if (modelMap.size() == 0) {
                    portfolioModel = AssetsQueryUtils.extractPortfolio(code, lookups, combMap.get(code), fundNetValueList, lastNetValues, portfolioMap, shareDetailQryPortfolioModels, null, dividendMap, mapIncome);
                } else {
                    portfolioModel = AssetsQueryUtils.extractPortfolio(code, lookups, combMap.get(code), fundNetValueList, lastNetValues, portfolioMap, shareDetailQryPortfolioModels, modelMap.get(code), dividendMap, mapIncome);
                }
                portfolioModel = AssetsQueryUtils.extractPortfolioByTrade(combTradeMap, lookups, portfolioModel, fundNetValueList);

                /*
                去掉的内容  不存表
                 */
//                portfolioModel = setBank(portfolioModel,userId);
//                FundCombination fundCombination = fundCombinationService.queryOne(code);
//                if (fundCombination != null && fundCombination.getAnnualizedIncome() != null) {
//                    portfolioModel.setShare("向您推荐一只基金组合，组合年化收益率为" + fundCombination.getAnnualizedIncome().toString() + "%");
//                } else {
//                    portfolioModel.setShare("向您推荐一只基金组合");
//                }
//                portfolioModels.add(portfolioModel);
            }
            //将组合存入资产页面组合模型中  并计算出组合的总资产和当日总收益  还有累计收益
            AssetPortfolioModel assetPortfolioModel = new AssetPortfolioModel();
            assetPortfolioModel.setPortfolios(portfolioModels);
            if (portfolioModels.size() != 0) {
                assetPortfolioModel.setNetValueDate(portfolioModels.get(0).getNetValueDate());
            } else {
                assetPortfolioModel.setNetValueDate(DateUtils.addDay(new Date(), -1));
            }

            BigDecimal portfolioWorthValue = new BigDecimal(0);
            BigDecimal portfolioTodayIncome = new BigDecimal(0);
            BigDecimal portfolioAccumIncome = new BigDecimal(0);

            int count = 0;
            //AssetPortfolioModel assetPortfolioForInTransit = AssetsQueryUtils.extractInTransit(lookups, applys, applyPortfolioCode);
            for (PortfolioModel portfolioModel : portfolioModels) {
                portfolioWorthValue = MoneyUtils.add(portfolioWorthValue, portfolioModel.getPortfolioWorthValue());
                portfolioTodayIncome = MoneyUtils.add(portfolioTodayIncome, portfolioModel.getPortfolioTodayIncome());
                portfolioAccumIncome = MoneyUtils.add(portfolioAccumIncome, portfolioModel.getPortfolioAccumIncome());
                count++;
            }
            //portfolioWorthValue = MoneyUtils.add(portfolioWorthValue, assetPortfolioForInTransit.getInTransitAmount());
            assetPortfolioModel.setPortfolioTodayIncome(portfolioTodayIncome);
            assetPortfolioModel.setPortfolioWorthValue(portfolioWorthValue);
            assetPortfolioModel.setPortfolioAccumIncome(portfolioAccumIncome);
            //assetPortfolioModel.setInTransitAmount(assetPortfolioForInTransit.getInTransitAmount());
            //assetPortfolioModel.setInTransit(assetPortfolioForInTransit.isInTransit());
            //assetPortfolioModel.setInTransitNum(assetPortfolioForInTransit.getInTransitNum());
            assetPortfolioModel.setPortfolioNum(count);
            // 计算份额，净值日期， 日收益率，万份收益
            List<AssetFundModel> funds = AssetsQueryUtils.extractFunds(shares, lookups, fundNetValueList);
            // 计算总和值，是否有在途
            // 汇总列表
            List<AssetFundModel> sumOfFunds = new ArrayList<>();
            // 零钱包 - 计算零钱包总资产和零钱包总收益
            // 零钱包资产要减去当前工作日已快速赎回的部分，因为快速赎回的部分当前工作日已经没有日收益
            Map<String, BigDecimal> mapDividend = new HashMap<>();
            AssetFundModel wallet = AssetsQueryUtils.sumOfAsset(funds, true, fastRedeemShares,
                null, todayFastRedeemShares, shareDetailQryFundModels, dividends, incomeModelsWallet, mapDividend);
            sumOfFunds.add(wallet);
            /**
             * Step 5-1: 计算累加收益
             */

            //算累计收益
            getAccumIncome(wallet, mapDividend, incomeModelsWallet);


            /**
             * 非组合基金的计算
             */
            // 排除组合后的基金  应该还是包括T0基金的  这里依旧沿用之前的方法  因为获取份额的恒生接口是同一个 所以没有太大的区别  排除掉组合份额后 就可以使用原方法
            //logger.warn("normalSize:{}", normalShares.size());

            List<AssetFundModel> normalFunds = AssetsQueryUtils.extractFunds(normalShares, lookups, fundNetValueList);
            AssetFundModel normalFund = AssetsQueryUtils.sumOfAsset(normalFunds, false, fastRedeemShares,
                lastNetValues, todayFastRedeemShares, shareDetailQryFundModels, dividends, incomeModelsNormal, mapDividend);
            for (AssetFundModel assetFundModel : normalFund.getFundModelList()) {
                // 获取基金类型
                NewsModel newsModel = queryService.getRiskLevel(assetFundModel.getFundCode());
                if (newsModel != null) {
                    assetFundModel.setFundType(newsModel.getFundType());
                }
            }
            // 总资产
            BigDecimal totalWorthValue = MoneyUtils.add(MoneyUtils.add(wallet.getTotalWorthValue(), normalFund.getTotalWorthValue()), assetPortfolioModel.getPortfolioWorthValue());
            // 总收益
            BigDecimal totalTodayIncome = MoneyUtils.add(MoneyUtils.add(wallet.getTotalTodayIncome(), normalFund.getTotalTodayIncome()), assetPortfolioModel.getPortfolioTodayIncome());
            //总累计收益
            BigDecimal totalAccumIncome = MoneyUtils.add(MoneyUtils.add(wallet.getTotalAccumIncome(), normalFund.getTotalAccumIncome()), assetPortfolioModel.getPortfolioAccumIncome());
            // 总在途金额
//            BigDecimal totalInTransitAmount = MoneyUtils.add(MoneyUtils.add(wallet.getInTransitAmount(), normalFund.getInTransitAmount()), assetPortfolioModel.getInTransitAmount());
            //总在途笔数
//            Integer totalInTransitNum = wallet.getInTransitNum() + normalFund.getInTransitNum() + assetPortfolioModel.getInTransitNum();

            // 返回结果
            result.setSuccess(true);
            // 零钱包
            result.setWallet(wallet);
            // 基金  非组合
            result.setFund(normalFund);
            // 总资产
            result.setTotalWorthValue(totalWorthValue);
            // 当日收益
            result.setTotalTodayIncome(totalTodayIncome);
            //累计收益
            result.setTotalAccumIncome(totalAccumIncome);
            // 总在途金额
//            result.setTotalInTransitAmount(totalInTransitAmount);
            //总在途笔数
//            result.setTotalInTransitNum(totalInTransitNum);
            //组合
            result.setPortfolios(assetPortfolioModel);

            return result;
        } catch (BaseException baseException) {
            throw baseException;
        } catch (Exception exception) {
            ExceptionUtil.logError(logger, "queryAssets - Exception:", exception);
            throw new SystemDBException("queryAssets Failure!", exception);
        }
    }

    @Override
    public BaseResult insertAssets(AssetsResult assets, Long userId) {
        insertUserAssets(assets, userId);
        insertPortfolioAssets(assets, userId);
        insertFundAssets(assets, userId);
        insertWalletAssets(assets, userId);
        BaseResult result = new BaseResult();
        return result;
    }

    //资产总表
    public Long insertUserAssets(AssetsResult assets, Long userId) {
        UserAssets userAssets = new UserAssets();
        userAssets.setUaCreateDate(new Date());
        userAssets.setUaEffectTime(getZeroTime());
        userAssets.setUaTotalAccumIncome(assets.getTotalAccumIncome());
        userAssets.setUaTotalAssets(assets.getTotalWorthValue());
        userAssets.setUaTotalTodayIncome(assets.getTotalTodayIncome());
        userAssets.setUaUpdateDate(new Date());
        userAssets.setUaUserId(userId);
        return userAssetsDao.insertByCode(userAssets);
    }

    //组合总资产
    public void insertPortfolioAssets(AssetsResult assets, Long userId) {
        PortfolioAssets portfolioAssets = new PortfolioAssets();
        portfolioAssets.setPaCreateDate(new Date());
        portfolioAssets.setPaEffectTime(getZeroTime());
        portfolioAssets.setPaPortfolioNum((long) assets.getPortfolios().getPortfolioNum());
        portfolioAssets.setPaPortfolioTotalAccumIncome(assets.getPortfolios().getPortfolioAccumIncome());
        portfolioAssets.setPaPortfolioTotalTodayIncome(assets.getPortfolios().getPortfolioTodayIncome());
        portfolioAssets.setPaTotalPortfolioAssets(assets.getPortfolios().getPortfolioWorthValue());
        portfolioAssets.setPaUpdateDate(new Date());
        portfolioAssets.setPaUserId(userId);
        Long portfolioAssetsId = portfolioAssetsDao.insertByCode(portfolioAssets);
        insertPortfolio(assets.getPortfolios(), portfolioAssetsId);
    }

    //基金总资产
    public void insertFundAssets(AssetsResult assets, Long userId) {
        FundAssets fundAssets = new FundAssets();
        fundAssets.setFaAccumIncome(assets.getFund().getTotalAccumIncome());
        fundAssets.setFaCreateDate(new Date());
        fundAssets.setFaEffectTime(getZeroTime());
        fundAssets.setFaFundNum(Long.valueOf(assets.getFund().getFundsCount()));
        fundAssets.setFaNetValueDate(assets.getFund().getNetValueDate());
        fundAssets.setFaTodayIncome(assets.getFund().getTotalTodayIncome());
        fundAssets.setFaTotalAssets(assets.getFund().getTotalWorthValue());
        fundAssets.setFaUpdateDate(new Date());
        fundAssets.setFaUserId(userId);
        Long fundAssetsId = fundAssetsDao.insertByCode(fundAssets);
        insertOneFund(assets.getFund(), fundAssetsId);
    }

    //瑞富宝总资产
    public void insertWalletAssets(AssetsResult assets, Long userId) {
        WalletAssets walletAssets = new WalletAssets();
        walletAssets.setWaAccumIncome(assets.getWallet().getTotalAccumIncome());
        walletAssets.setWaCreateDate(new Date());
        walletAssets.setWaEffectTime(getZeroTime());
        walletAssets.setWaNetValueDate(assets.getWallet().getNetValueDate());
        walletAssets.setWaTodayIncome(assets.getWallet().getTotalTodayIncome());
        walletAssets.setWaTotalAssets(assets.getWallet().getTotalWorthValue());
        walletAssets.setWaUpdateDate(new Date());
        walletAssets.setWaUserId(userId);
        Long walletAssetsId = walletAssetsDao.insertByCode(walletAssets);
        insertOneWallet(assets.getWallet(), walletAssetsId);
    }

    //组合
    public void insertPortfolio(AssetPortfolioModel assetPortfolioModel, Long portfolioAssetsId) {
        for (PortfolioModel portfolioModel : assetPortfolioModel.getPortfolios()) {
            OnePortfolio onePortfolio = new OnePortfolio();
            onePortfolio.setOpCreateDate(new Date());
            onePortfolio.setOpEffectTime(getZeroTime());
            onePortfolio.setOpNetValueDate(portfolioModel.getNetValueDate());
            onePortfolio.setOpOnePortfolioAccumIncome(portfolioModel.getPortfolioAccumIncome());
            onePortfolio.setOpOnePortfolioAssets(portfolioModel.getPortfolioWorthValue());
            onePortfolio.setOpOnePortfolioTodayIncome(portfolioModel.getPortfolioTodayIncome());
            onePortfolio.setOpPortfolioCanSell(portfolioModel.isCanSell());
            onePortfolio.setOpPortfolioCode(portfolioModel.getPortfolioCode());
            onePortfolio.setOpPortfolioAssetsId(portfolioAssetsId);
            onePortfolio.setOpPortfolioCurrentShare(portfolioModel.getCurrentShare());
            onePortfolio.setOpPortfolioEnableShare(portfolioModel.getEnableShare());
            onePortfolio.setOpPortfolioName(portfolioModel.getProtocolName());
            onePortfolio.setOpShareWord(portfolioModel.getShare());
            onePortfolio.setOpUpdateDate(new Date());
            onePortfolio.setOpTradeAccount(portfolioModel.getTradeAcco());
            Long onePortfolioId = onePortfolioDao.insertByCode(onePortfolio);
            insertPortfolioFund(portfolioModel, onePortfolioId);
            insertPortfolioTrade(portfolioModel, onePortfolioId);
        }
    }

    //组合基金
    public void insertPortfolioFund(PortfolioModel portfolioModel, Long onePortfolioId) {
        for (AssetFundModel assetFundModel : portfolioModel.getPortfolioFunds()) {
            PortfolioFund portfolioFund = new PortfolioFund();
            portfolioFund.setPfAccumIncome(assetFundModel.getTotalAccumIncome());
            portfolioFund.setPfAssetType(String.valueOf(assetFundModel.getAssetType()));
            portfolioFund.setPfAutoBuy(Boolean.valueOf(assetFundModel.getAutoBuy()));
            portfolioFund.setPfCreateDate(new Date());
            portfolioFund.setPfDailyProfit(assetFundModel.getDailyProfit());
            portfolioFund.setPfEffectTime(getZeroTime());
            portfolioFund.setPfFundCode(assetFundModel.getFCode());
            portfolioFund.setPfFundCurrentShare(assetFundModel.getCurrentShares());
            portfolioFund.setPfFundEnableShare(assetFundModel.getEnableShares());
            portfolioFund.setPfFundInvestRate(assetFundModel.getInvestRate());
            portfolioFund.setPfFundName(assetFundModel.getFundName());
            portfolioFund.setPfFundTodayIncome(assetFundModel.getTotalTodayIncome());
            portfolioFund.setPfFundWorthValue(assetFundModel.getTotalWorthValue());
            portfolioFund.setPfIsCurrency(assetFundModel.getIsCurrency());
            portfolioFund.setPfNetValue(assetFundModel.getNetValue());
            portfolioFund.setPfNetValueDate(assetFundModel.getNetValueDate());
            portfolioFund.setPfOnePortfolioId(onePortfolioId);
            portfolioFund.setPfTodayIncomeRate(assetFundModel.getTodayIncomeRate());
            portfolioFund.setPfTradeAccount(assetFundModel.getTradeAcco());
            portfolioFund.setPfUnpaidIncome(assetFundModel.getUnpaidIncome());
            portfolioFund.setPfUpdateDate(new Date());
            portfolioFundDao.insertByCode(portfolioFund);
        }
    }

    //交易账号粒度 组合
    public void insertPortfolioTrade(PortfolioModel portfolioModel, Long onePortfolioId) {
        for (PortfolioTradeModel portfolioTradeModel : portfolioModel.getPortfolioTrades()) {
            PortfolioTrade portfolioTrade = new PortfolioTrade();
            portfolioTrade.setPtBankCode(portfolioTradeModel.getBankCode());
            portfolioTrade.setPtBankName(portfolioTradeModel.getBankName());
            portfolioTrade.setPtBankNo(portfolioTradeModel.getUserBankNo());
            portfolioTrade.setPtCapitalMode(portfolioTradeModel.getCapitalMode());
            portfolioTrade.setPtCreateDate(new Date());
            portfolioTrade.setPtEffectTime(getZeroTime());
            portfolioTrade.setPtOnePortfolioAssets(portfolioTradeModel.getTotalWorthValue());
            portfolioTrade.setPtOnePortfolioTodayIncome(portfolioTradeModel.getTotalTodayIncome());
            portfolioTrade.setPtOnePortfolioId(onePortfolioId);
            portfolioTrade.setPtPortfolioCode(portfolioTradeModel.getPortfolioCode());
            portfolioTrade.setPtPortfolioCurrentShare(portfolioTradeModel.getCurrentShare());
            portfolioTrade.setPtPortfolioEnableShare(portfolioTradeModel.getEnableShare());
            portfolioTrade.setPtTradeAccount(portfolioTradeModel.getTradeAcco());
            portfolioTrade.setPtUpdateDate(new Date());
            Long portfolioTradeId = portfolioTradeDao.insertByCode(portfolioTrade);
            insertPortfolioTradeFund(portfolioTradeModel, portfolioTradeId);
        }
    }

    //交易账号粒度组合基金
    public void insertPortfolioTradeFund(PortfolioTradeModel portfolioTradeModel, Long portfolioTradeId) {
        for (AssetFundModel assetFundModel : portfolioTradeModel.getPortfolioFunds()) {
            PortfolioFundTrade portfolioFundTrade = new PortfolioFundTrade();
            portfolioFundTrade.setPftAccumIncome(assetFundModel.getTotalAccumIncome());
            portfolioFundTrade.setPftAssetType(String.valueOf(assetFundModel.getAssetType()));
            portfolioFundTrade.setPftAutoBuy(Boolean.valueOf(assetFundModel.getAutoBuy()));
            portfolioFundTrade.setPftCreateDate(new Date());
            portfolioFundTrade.setPftDailyProfit(assetFundModel.getDailyProfit());
            portfolioFundTrade.setPftEffectTime(getZeroTime());
            portfolioFundTrade.setPftFundCode(assetFundModel.getFCode());
            portfolioFundTrade.setPftFundCurrentShare(assetFundModel.getCurrentShares());
            portfolioFundTrade.setPftFundEnableShare(assetFundModel.getEnableShares());
            portfolioFundTrade.setPftFundInvestRate(assetFundModel.getInvestRate());
            portfolioFundTrade.setPftFundName(assetFundModel.getFundName());
            portfolioFundTrade.setPftFundTodayIncome(assetFundModel.getTotalTodayIncome());
            portfolioFundTrade.setPftFundWorthValue(assetFundModel.getTotalWorthValue());
            portfolioFundTrade.setPftIsCurrency(assetFundModel.getIsCurrency());
            portfolioFundTrade.setPftNetValue(assetFundModel.getNetValue());
            portfolioFundTrade.setPftNetValueDate(assetFundModel.getNetValueDate());
            portfolioFundTrade.setPftPortfolioTradeId(portfolioTradeId);
            portfolioFundTrade.setPftTodayIncomeRate(assetFundModel.getTodayIncomeRate());
            portfolioFundTrade.setPftTradeAccount(assetFundModel.getTradeAcco());
            portfolioFundTrade.setPftUnpaidIncome(assetFundModel.getUnpaidIncome());
            portfolioFundTrade.setPftUpdateDate(new Date());
            portfolioFundTradeDao.insertByCode(portfolioFundTrade);
        }
    }

    //普通基金
    public void insertOneFund(AssetFundModel assetFundModelOut, Long fundAssetsId) {
        for (AssetFundModel assetFundModel : assetFundModelOut.getFundModelList()) {
            OneFund oneFund = new OneFund();
            oneFund.setOfAccumIncome(assetFundModel.getTotalAccumIncome());
            oneFund.setOfAssetType(String.valueOf(assetFundModel.getAssetType()));
            oneFund.setOfAutoBuy(Boolean.valueOf(assetFundModel.getAutoBuy()));
            oneFund.setOfCreateDate(new Date());
            oneFund.setOfDailyProfit(assetFundModel.getDailyProfit());
            oneFund.setOfEffectTime(getZeroTime());
            oneFund.setOfFundCode(assetFundModel.getFCode());
            oneFund.setOfFundCurrentShare(assetFundModel.getCurrentShares());
            oneFund.setOfFundEnableShare(assetFundModel.getEnableShares());
            oneFund.setOfFundName(assetFundModel.getFundName());
            oneFund.setOfFundTodayIncome(assetFundModel.getTotalTodayIncome());
            oneFund.setOfFundWorthValue(assetFundModel.getTotalWorthValue());
            oneFund.setOfIsCurrency(assetFundModel.getIsCurrency());
            oneFund.setOfNetValue(assetFundModel.getNetValue());
            oneFund.setOfNetValueDate(assetFundModel.getNetValueDate());
            oneFund.setOfFundAssetsId(fundAssetsId);
            oneFund.setOfTodayIncomeRate(assetFundModel.getTodayIncomeRate());
            oneFund.setOfTradeAccount(assetFundModel.getTradeAcco());
            oneFund.setOfUnpaidIncome(assetFundModel.getUnpaidIncome());
            oneFund.setOfUpdateDate(new Date());
            oneFund.setOfBankCode(assetFundModel.getBankCode());
            oneFund.setOfBankName(assetFundModel.getBankName());
            oneFund.setOfBankNo(assetFundModel.getUserBankNo());
            oneFund.setOfCapitalMode(assetFundModel.getCapitalMode());
            oneFund.setOfDividendsWord(assetFundModel.getDividends());
            oneFund.setOfFundType(assetFundModel.getFundType());
            oneFund.setOfFundTypeApp(String.valueOf(assetFundModel.getAppFundType()));
            oneFundDao.insertByCode(oneFund);
        }
    }

    //T0基金
    public void insertOneWallet(AssetFundModel assetFundModelOut, Long walletAssetsId) {
        for (AssetFundModel assetFundModel : assetFundModelOut.getFundModelList()) {
            OneWallet oneWallet = new OneWallet();
            oneWallet.setOwAccumIncome(assetFundModel.getTotalAccumIncome());
            oneWallet.setOwAssetType(String.valueOf(assetFundModel.getAssetType()));
            oneWallet.setOwAutoBuy(Boolean.valueOf(assetFundModel.getAutoBuy()));
            oneWallet.setOwCreateDate(new Date());
            oneWallet.setOwDailyProfit(assetFundModel.getDailyProfit());
            oneWallet.setOwEffectTime(getZeroTime());
            oneWallet.setOwFundCode(assetFundModel.getFCode());
            oneWallet.setOwFundCurrentShare(assetFundModel.getCurrentShares());
            oneWallet.setOwFundEnableShare(assetFundModel.getEnableShares());
            oneWallet.setOwFundName(assetFundModel.getFundName());
            oneWallet.setOwFundTodayIncome(assetFundModel.getTotalTodayIncome());
            oneWallet.setOwFundWorthValue(assetFundModel.getTotalWorthValue());
            oneWallet.setOwNetValue(assetFundModel.getNetValue());
            oneWallet.setOwNetValueDate(assetFundModel.getNetValueDate());
            oneWallet.setOwWalletAssetsId(walletAssetsId);
            oneWallet.setOwTradeAccount(assetFundModel.getTradeAcco());
            oneWallet.setOwUnpaidIncome(assetFundModel.getUnpaidIncome());
            oneWallet.setOwUpdateDate(new Date());
            oneWallet.setOwBankCode(assetFundModel.getBankCode());
            oneWallet.setOwBankName(assetFundModel.getBankName());
            oneWallet.setOwBankNo(assetFundModel.getUserBankNo());
            oneWallet.setOwCapitalMode(assetFundModel.getCapitalMode());
            oneWallet.setOwDividendsWord(assetFundModel.getDividends());
            oneWalletDao.insertByCode(oneWallet);
        }
    }

    /**
     * 获取上一工作日的净值，getFundNetValue会找出比lastDate小的最新的净值
     * <p>
     * Shangdu Lin - 20170417
     *
     * @param fundCode
     * @param currentWorkingDate
     * @return
     */
    private BigDecimal getLastUnitValue(String fundCode, Date currentWorkingDate) {
        // 获取前一工作日的净值
        Date lastDate = DateUtils.addDay(currentWorkingDate, -1);
        FundNetValueResult result = fundDetailService.getFundNetValue(fundCode, lastDate);
        if (!result.getSuccess()) {
            throw new BaseException(ErrorConstant.ERROR_GILDATA_WRONG, result.getErrorMessage(), GlobalConstant.ERROR_TYPE_APPLICATION);
        }

        return result.getUnitNV();
    }

    /**
     * 计算出前后30天未T+1确认的实时成功的快速赎回的份额 - Shangdu Lin
     * 如果要精确计算的话，只要算当前工作日以及上一工作日的未T+1确认的实时成功的快速赎回的份额
     *
     * @param userId
     * @param currentDate
     * @param interval
     * @return
     * @throws BaseException
     */
    public Map<String, BigDecimal> getFastRedeemSharesWithInterval(Long userId, Date currentDate, Integer interval)
        throws BaseException {
        try {

            Date beginDate = DateUtils.addDay(currentDate, interval * (-1));
            Date endDate = DateUtils.addDay(currentDate, interval);

            ApplyListResult applyListResult = queryApplys(userId, beginDate, endDate,
                GlobalConstant.FUND_BUSIN_CODE_T0_FAST_APPLY_SELL, GlobalConstant.TACONFIRM_FLAG_REAL_SUCCESS,
                true);
            if (!applyListResult.getSuccess()) {
                throw new BaseException(applyListResult.getErrorCode(), applyListResult.getErrorMessage());
            }

            return AssetsQueryUtils.getFastSellShares(applyListResult.getApplys());
        } catch (BaseException baseException) {
            throw baseException;
        } catch (Exception exception) {
            ExceptionUtil.logError(logger, "getFastRedeemShares - Exception:", exception);
            throw new SystemDBException("getFastRedeemShares Failure!", exception);
        }
    }

    /**
     * Shangdu Lin: 查询某一用户下的某一时间段的所有交易记录, 此方法被用于计算当前交易日T0基金快速赎回限制
     *
     * @param userId
     * @param beginDate
     * @param endDate
     * @param businCode
     * @param onlyT0
     * @return
     * @throws BaseException
     */
    public ApplyListResult queryApplys(Long userId, Date beginDate, Date endDate, String businCode, String confirmFlag,
                                       boolean onlyT0) throws BaseException {

        ApplyListResult result = new ApplyListResult();

        try {

            // 获取用户
            User user = userDao.getEntity(userId);

            // 判断是否已开户
            if (user == null || StringUtil.isEmpty(user.getExternalClientId())) {
                result.setSuccess(false);
                result.setErrorType(GlobalConstant.ERROR_TYPE_APPLICATION);
                result.setErrorCode(ErrorConstant.ERROR_NO_ACCOUNT);
                return result;
            }

            String beginDateString = DateUtils.formatDate4(beginDate);
            String endDateString = DateUtils.formatDate4(endDate);
            // 查出这个用户下当前时间段所有的交易记录，包括已确认和未确认的，传ClientId
            Map<String, Object> map = tradeApplyQueryService.query(GlobalConstant.MAX_REQUEST_NUM, 1, 1, "1", "",
                user.getExternalClientId(), beginDateString, endDateString, "", confirmFlag, "", "", businCode, "",
                "", "", "", "");

            // 查询结果
            List<Map<String, Object>> list = new ArrayList<>();
            HundsunUtils.ConvertToList(map, list, result);
            if (!result.getSuccess()) {
                return result;
            }

            // 交易业务名称
            List<Lookup> tradeLookups = lookupDao.getLookupByType(RuleConstant.RULE_LOOKUP_TYPE_BUSINAME);
            // 银行名称
            List<Lookup> bankLookups = lookupDao.getLookupByType(RuleConstant.RULE_LOOKUP_TYPE_HSBANK);
            // populate
            List<ApplyModel> applys = ModelPopulateUtils.populateApply(list, result, tradeLookups, bankLookups);
            // 只计算T0基金
            if (onlyT0) {
                List<Lookup> T0Funds = lookupDao.getLookupByType(RuleConstant.RULE_LOOKUP_TYPE_T0FUND);
                Iterator<ApplyModel> iterator = applys.iterator();
                while (iterator.hasNext()) {
                    ApplyModel model = iterator.next();
                    if (!ModelPopulateUtils.isT0Fund(T0Funds, model.getFundCode())) {
                        iterator.remove();
                    }
                }
            }

            result.setSuccess(true);
            result.setApplys(applys);

            return result;

        } catch (BaseException baseException) {
            throw baseException;
        } catch (Exception exception) {
            ExceptionUtil.logError(logger, "queryApplys - Exception:", exception);
            throw new SystemDBException("queryApplys Failure!", exception);
        }
    }

    /**
     * 获取某一用户当前工作日未T+1确认实时成功的快速赎回的份额
     *
     * @param userId
     * @param currentDate
     * @return
     */
    public Map<String, BigDecimal> getCurrentWorkingDayFastRedeemShares(Long userId, Date currentDate,
                                                                        boolean isWorkingDate) throws BaseException {
        try {

            Date beginDate = new Date();
            Date endDate = new Date();

            if (!isWorkingDate) {
                WorkingDayResult workingDaysResult = workingDateService.getWorkingDays(currentDate);
                if (!workingDaysResult.getSuccess()) {
                    throw new BaseException(workingDaysResult.getErrorCode(), workingDaysResult.getErrorMessage());
                }

                List<Date> workingDays = workingDaysResult.getWorkingDates();
                if (workingDays.size() == 0) {
                    throw new BaseException(ErrorConstant.ERROR_WORKING_DATE_NO_FIND);
                }

                beginDate = workingDays.get(0);
                endDate = workingDays.get(0);
                if (workingDays.size() > 1) {
                    endDate = workingDays.get(1);
                }
            } else {
                beginDate = currentDate;
                endDate = currentDate;
            }

            ApplyListResult applyListResult = queryApplys(userId, beginDate, endDate,
                GlobalConstant.FUND_BUSIN_CODE_T0_FAST_APPLY_SELL, GlobalConstant.TACONFIRM_FLAG_REAL_SUCCESS,
                true);
            if (!applyListResult.getSuccess()) {
                throw new BaseException(applyListResult.getErrorCode(), applyListResult.getErrorMessage());
            }

            return AssetsQueryUtils.getFastSellShares(applyListResult.getApplys());
        } catch (BaseException baseException) {
            throw baseException;
        } catch (Exception exception) {
            ExceptionUtil.logError(logger, "getFastRedeemShares - Exception:", exception);
            throw new SystemDBException("getFastRedeemShares Failure!", exception);
        }
    }

    /**
     * 交易确认查询
     *
     * @param userId
     * @param requestNum
     * @param queryFlag
     * @param beginNum
     * @param sortDirection
     * @param fundCode
     * @param businCode
     * @param beginDate
     * @param endDate
     * @param confirmFlag
     * @return
     */
    public CollectionResult<ConfirmModel> queryTradeConfirms(Long userId, Integer requestNum, Integer queryFlag, Integer beginNum,
                                                             String sortDirection, String fundCode, String businCode, Date beginDate, Date endDate, String confirmFlag) {

        CollectionResult<ConfirmModel> result = new CollectionResult<>();
        try {

            // 获取用户
            User user = userDao.getEntity(userId);

            // 判断是否已开户
            if (user == null || StringUtil.isEmpty(user.getExternalClientId())) {
                result.setSuccess(false);
                result.setErrorType(GlobalConstant.ERROR_TYPE_APPLICATION);
                result.setErrorCode(ErrorConstant.ERROR_NO_ACCOUNT);
                return result;
            }

            Map<String, Object> map = tradeConfirmQueryService.query(requestNum, queryFlag, beginNum, sortDirection, "", user.getExternalClientId(), DateUtils.formatDate4(beginDate), DateUtils.formatDate4(endDate), "", confirmFlag, "", fundCode, businCode, "", "", "", "", "", "", "");

            // 查询结果
            List<Map<String, Object>> list = new ArrayList<>();
            HundsunUtils.ConvertToList(map, list, result);
            if (!result.getSuccess()) {
                return result;
            }

            // populate
            List<ConfirmModel> confirms = ModelPopulateUtils.populateConfirm(list);

            result.setObjs(confirms);

            return result;

        } catch (BaseException baseException) {
            throw baseException;
        } catch (Exception exception) {
            ExceptionUtil.logError(logger, "queryTradeConfirms - Exception:", exception);
            throw new SystemDBException("queryTradeConfirms Failure!", exception);
        }
    }

    /**
     * 根据交易账号查分红明细
     *
     * @param key
     * @return
     */
    private void getDividends(String key, User user, Map<String, List<DividendModel>> dividendMap) {
        Map<String, Object> map = dividendsQueryService.query(GlobalConstant.MAX_REQUEST_NUM, 1, 1, "1", key, "", user.getExternalClientId(), "");
        List<Map<String, Object>> list = new ArrayList<>();
        PortfolioModel result = new PortfolioModel();
        HundsunUtils.ConvertToList(map, list, result);

        if (!result.getSuccess()) {
            throw new BaseException(result.getErrorCode(), result.getErrorMessage());
        }
        // populate
        BaseListResult baseListResult = new BankListResult();
        List<DividendModel> dividends = ModelPopulateUtils.populateDividend(list, baseListResult);
        dividendMap.put(key, dividends);
    }

    /**
     * 累加分红 - add by Shangdu Lin - 20170612
     *
     * @param clientId
     * @param fundCode
     * @return
     */
    private BigDecimal sumOfDividends(String clientId, String fundCode) {
        /**
         * Step 1: 分红明细查询
         */
        // 查询该用户下的所有份额
        Map<String, Object> map = dividendsQueryService.query(GlobalConstant.MAX_REQUEST_NUM, 1, 1, "1", "", "", clientId, fundCode);

        // 查询结果
        BaseResult result = new BaseResult();
        List<Map<String, Object>> list = new ArrayList<>();
        HundsunUtils.ConvertToList(map, list, result);
        for (Map<String, Object> map1 : list) {
            //logger.info("恒生返回 分红明细 基金编码：{}，红利金额：{}",map1.get(HSOutputParameterNames.FUND_CODE), map1.get(HSOutputParameterNames.DIVIDEND_TOTALBALA));
        }
        if (!result.getSuccess()) {
            throw new BaseException(result.getErrorCode(), result.getErrorMessage());
        }

        // populate
        BaseListResult baseListResult = new BankListResult();
        List<DividendModel> dividends = ModelPopulateUtils.populateDividend(list, baseListResult);
        if (CollectionUtils.isEmpty(dividends)) {
            return null;
        }

        /**
         * Step 2: 累加分红
         */
        BigDecimal totalDividends = new BigDecimal(0);
        for (DividendModel dividend :
            dividends) {
            totalDividends = MoneyUtils.add(totalDividends, dividend.getTotalDividendBalance());
            //logger.info("分红：{}", dividend.getTotalDividendBalance());
        }

        return totalDividends;
    }

    private PortfolioModel setBank(PortfolioModel portfolioModel, Long userId) {
        if (portfolioModel != null && portfolioModel.getPortfolioTrades() != null) {

            // 查询用户银行卡列表
            User user = userService.getUser(userId);
            if (Strings.isNullOrEmpty(user.getExternalClientId())) {
                return portfolioModel;
            }
            HsAccoBankQueryDto queryDto = HsAccoBankQueryDto.builder()
                .client_id(user.getExternalClientId())
                .build();
            List<HsAccoBankQueryResponse> hsBanks = accountBankQuery.query(queryDto);
            if (hsBanks != null) {
                List<PortfolioTradeModel> portfolioTrades = portfolioModel.getPortfolioTrades();
                portfolioTrades.forEach(item -> {
                    String portfolioTradeAcco = item.getTradeAcco();

                    for (HsAccoBankQueryResponse queryResponse : hsBanks) {

                        if (EqualsUtil.equals(portfolioTradeAcco, queryResponse.getTrade_acco())) {

                            List<UserBank> userBanks = bankService.getBanks(user.getUserId(), queryResponse.getBank_account());

                            if (userBanks == null || userBanks.isEmpty()) {
                                logger.warn("userId={},bankNo={}不存在", user.getUserId(), queryResponse.getBank_account());
                            } else {
                                UserBank userBank = userBanks.get(0);
                                item.setUserBankNo(userBank.getUserBankNo());
                                item.setBankName(userBank.getBankName());
                                item.setBankCode(userBank.getBankCode());
                                item.setBranchBank(userBank.getBranchbank() == null ? "" : userBank.getBranchbank());
                                item.setBranchBankName(userBank.getBankBranchName() == null ? "" : userBank.getBankBranchName());
                                item.setCapitalMode(userBank.getCapitalMode());
                            }
                            break;
                        }
                    }


                });
            } else {
                logger.warn("没有该账户对应的银行卡交易账号信息");
            }
        }
        return portfolioModel;
    }

    private void getAccumIncome(AssetFundModel wallet, Map<String, BigDecimal> mapDividend, List<IncomeModel> incomeModels) {
        BigDecimal totalAccumIncome = new BigDecimal(0);
        List<String> fundCodes = new ArrayList<>();
        //算出累计收益后  总资产需要加上累计收益 所以要重新算一遍
        if (wallet.getFundModelList() != null) {
            List<AssetFundModel> aList = wallet.getFundModelList();
            //BigDecimal worthValue = null;
            //BigDecimal totalUnpaidIncome = null;
            for (AssetFundModel m : aList) {
                // 获得红利总金额
                BigDecimal totalDividends = mapDividend.get(m.getFundCode());
                // 累计收益 = 每月5号06文件中的“红利资金” + 每日05文件中的“货币基金未分配收益金额”
                BigDecimal temp = MoneyUtils.add(totalDividends, m.getUnpaidIncome());
                m.setTotalAccumIncome(temp);
                totalAccumIncome = MoneyUtils.add(totalAccumIncome, temp);
                fundCodes.add(m.getFundCode());
                //logger.warn("基金：{}，累计收益：{}，红利资金：{}，货币基金未分配收益金额：{}", m.getFundCode(), m.getTotalAccumIncome(), totalDividends, m.
                //getUnpaidIncome());
            }
        }
        for (IncomeModel incomeModel : incomeModels) {
            if (!fundCodes.contains(incomeModel.getFundCode())) {
                totalAccumIncome = MoneyUtils.add(totalAccumIncome, incomeModel.getAccumIncome());
            }
        }
        wallet.setTotalAccumIncome(totalAccumIncome);
    }

    @Override
    public PortfolioModel extractPortfolioForProfit(List<CombSharesQryModel> combSharesQryModels, List<FundNetValueResult> fundNetValueList,
                                                    Map<String, List<DividendModel>> dividendMap,
                                                    List<ConfirmModel> confirms, Long userId, String clientId) {
        PortfolioModel portfolioModel = new PortfolioModel();
        List<AssetFundModel> portfolioFunds = new ArrayList<>();
        BigDecimal portfolioWorthValue = null;
        BigDecimal portfolioTodayIncome = null;
        BigDecimal portfolioAccumIncome = null;
        BigDecimal portfolioDividend = new BigDecimal(0);
        Date netValueDate = DateUtils.addDay(new Date(), -1); //默认净值日期为前一天
//        boolean                         portfolioInTransit    = false;
//        int                             portfolioInTransitNum = 0;
//        BigDecimal                      portfolioInTransitSum = new BigDecimal(0);
        for (CombSharesQryModel combSharesQryModel : combSharesQryModels) {
            FundNetValueResult netValueResult = null;
            BigDecimal currentShare = combSharesQryModel.getFundShare();
            BigDecimal enableShare = combSharesQryModel.getEnableShares();
            if (MoneyUtils.compareTo(currentShare, 0) == 0) {
                continue;
            }
            String portfolioCode = combSharesQryModel.getPortfolioCode();
            String fundCode = combSharesQryModel.getFundCode();

            AssetFundModel assetFundModel = new AssetFundModel();
            netValueResult = CalculateAssetsUtils.setNetValue(fundCode, netValueResult, fundNetValueList);
            //交易账号
            assetFundModel.setTradeAcco(combSharesQryModel.getTradeAcco());
            //基金代码
            assetFundModel.setFundCode(combSharesQryModel.getFundCode());
            //基金份额
            assetFundModel.setCurrentShares(currentShare);
            //可用份额
            assetFundModel.setEnableShares(enableShare);
            // 单位净值
            assetFundModel.setNetValue(netValueResult.getUnitNV());
            //基金名称
            assetFundModel.setFundName(netValueResult.getChiNameAbbr());
            // 单位净值日期
            assetFundModel.setNetValueDate(netValueResult.getTradingDay());
            //获取实际的净值日期
            netValueDate = netValueResult.getTradingDay();
            // 资产类型
            assetFundModel.setAssetType(GlobalConstant.ASSET_TYPE_FUND);


            List<DividendModel> dividends = dividendMap.get(combSharesQryModel.getTradeAcco());


            //总的现金分红   用于累计收益
            BigDecimal totalDividend = new BigDecimal(0);
            if (dividends != null && !dividends.isEmpty()) {
                for (DividendModel dividendModel : dividends) {
                    if ("1".equals(dividendModel.getAutoBuy()) && combSharesQryModel.getTradeAcco().equals(dividendModel.getTradeAccount()) && assetFundModel.getFundCode().equals(dividendModel.getFundCode())) {
                        if (dividendModel.getDividendDate().compareTo(DateUtils.formatDate4(new Date())) < 0) {
                            totalDividend = MoneyUtils.add(totalDividend, dividendModel.getDividendBalance());
                        }
                    }
                }
            }


            BigDecimal worthValue = currentShare.multiply(assetFundModel.getNetValue());

            //累计收益   新方案为 资产 加 赎回金额 减去 申购金额 加上现金分红
            BigDecimal accumIncome = MoneyUtils.add(worthValue, totalDividend);
            logger.debug("累计收益:{}", accumIncome);

            for (ConfirmModel confirm : confirms) {
                //需要 交易账号 基金编号都相同
                if (confirm.getTradeAcco().equals(assetFundModel.getTradeAcco()) && confirm.getFundCode().equals(assetFundModel.getFundCode())) {
                    if (confirm.getTAConfirmFlag().equals(GlobalConstant.TACONFIRM_FLAG_CONFIRMED)) {
                        if (confirm.getFundBusinCode().equals(GlobalConstant.FUND_BUSIN_CODE_CONFIRM_BUY)) {
                            accumIncome = MoneyUtils.subtract(accumIncome, confirm.getTradeConfirmBalance());
                            logger.debug("组合申购金额:{}", confirm.getTradeConfirmBalance());
                            logger.debug("累计收益:{}", accumIncome);

                        }
                        if (confirm.getFundBusinCode().equals(GlobalConstant.FUND_BUSIN_CODE_CONFIRM_SELL)) {
                            accumIncome = MoneyUtils.add(accumIncome, confirm.getTradeConfirmBalance());
                            logger.debug("组合赎回金额:{}", confirm.getTradeConfirmBalance());
                            logger.debug("累计收益:{}", accumIncome);


                        }
                    }
                }
            }
            assetFundModel.setTotalAccumIncome(accumIncome);
            Profit profit = new Profit();
            //profit.setProfitValue(accumIncome);
            profit.setFundCode(assetFundModel.getFundCode());
            profit.setTradeAcco(assetFundModel.getTradeAcco());
            //profit.setCreateTime(DateUtils.getFormatedDate(new Date(), "yyyy-MM-dd HH:mm:ss"));
            profit.setDateTime(DateUtils.getFormatedDate(DateUtils.addDay(new Date(), -1), "yyyy-MM-dd"));
            profit.setUserId(userId.intValue());
            profit.setClientId(clientId);
            Profit profit1 = null;
            List<Profit> profits = profitDao.selectNewProfit(userId.intValue(), clientId, assetFundModel.getTradeAcco(), assetFundModel.getFundCode());
            if (!profits.isEmpty()) {
                profit1 = profits.get(0);
            }
            if (profit1 != null) {
                profit1.setAccumulateProfitValue(accumIncome);
                profitDao.updateByPrimaryKeySelective(profit1);
            }


            worthValue = worthValue.setScale(2, BigDecimal.ROUND_HALF_UP);
            //设置每个基金的资产
            assetFundModel.setTotalWorthValue(worthValue);

            portfolioFunds.add(assetFundModel);
            portfolioWorthValue = MoneyUtils.add(portfolioWorthValue, worthValue);
            portfolioDividend = MoneyUtils.add(totalDividend, portfolioDividend);
        }
        portfolioModel.setTradeAcco(combSharesQryModels.get(0).getTradeAcco());
        return portfolioModel;
    }

    @Override
    public BigDecimal getPortfolioAccumIncomeForProfit(List<ConfirmModel> confirms, List<String> portfolioTradeAccounts, Map<String, List<DividendModel>> dividendMap, Long userId, String clientId) {
        //累计收益加上全赎    和分红
        //需要将全赎的交易账号提取出来  用于获取这个交易账号的 全部分红
        Map<String, AccumModel> map = new HashMap<>();
        Set<String> noFundTradeAccount = new HashSet<>();
        for (ConfirmModel confirm : confirms) {
            if (confirm.getTradeAcco().startsWith("ZH") && !portfolioTradeAccounts.contains(confirm.getTradeAcco())) {
                noFundTradeAccount.add(confirm.getTradeAcco());
                BigDecimal accumIncome = new BigDecimal(0);
                logger.debug("全赎的交易账号：{}", confirm.getTradeAcco());
                if (confirm.getTAConfirmFlag().equals(GlobalConstant.TACONFIRM_FLAG_CONFIRMED)) {
                    if (confirm.getFundBusinCode().equals(GlobalConstant.FUND_BUSIN_CODE_CONFIRM_BUY)) {
                        accumIncome = MoneyUtils.subtract(accumIncome, confirm.getTradeConfirmBalance());
                    }
                    if (confirm.getFundBusinCode().equals(GlobalConstant.FUND_BUSIN_CODE_CONFIRM_SELL)) {
                        accumIncome = MoneyUtils.add(accumIncome, confirm.getTradeConfirmBalance());
                    }
                }
                String key = confirm.getFundCode() + confirm.getTradeAcco();
                AccumModel accumModel = AccumModel.builder().
                    accumIncome(accumIncome).
                    fundCode(confirm.getFundCode()).
                    tradeAccount(confirm.getTradeAcco()).
                    build();
                if (map.containsKey(key)) {
                    map.put(key, map.get(key).setAccumIncome(MoneyUtils.add(map.get(key).getAccumIncome(), accumIncome)));
                } else {
                    map.put(key, accumModel);
                }
            }
        }
        for (String tradeAccount : noFundTradeAccount) {
            if (dividendMap.get(tradeAccount) != null && !dividendMap.get(tradeAccount).isEmpty()) {
                for (DividendModel dividendModel : dividendMap.get(tradeAccount)) {
                    if ("1".equals(dividendModel.getAutoBuy()) && tradeAccount.equals(dividendModel.getTradeAccount())) {
                        if (dividendModel.getDividendDate().compareTo(DateUtils.formatDate4(new Date())) < 0) {
                            logger.debug("有分红 ：{}", dividendModel.getDividendBalance());
                            String key = dividendModel.getFundCode() + dividendModel.getTradeAccount();
                            AccumModel accumModel = AccumModel.builder().
                                accumIncome(dividendModel.getDividendBalance()).
                                fundCode(dividendModel.getFundCode()).
                                tradeAccount(dividendModel.getTradeAccount()).
                                build();
                            if (map.containsKey(key)) {
                                map.put(key, map.get(key).setAccumIncome(MoneyUtils.add(map.get(key).getAccumIncome(), dividendModel.getDividendBalance())));
                            } else {
                                map.put(key, accumModel);
                            }
                        }
                    }
                }
            }
        }
        for (String ft : map.keySet()) {
            Profit profit = new Profit();
            profit.setAccumulateProfitValue(map.get(ft).getAccumIncome());
            profit.setProfitValue(map.get(ft).getAccumIncome());
            profit.setFundCode(map.get(ft).getFundCode());
            profit.setTradeAcco(map.get(ft).getTradeAccount());
            profit.setCreateTime(DateUtils.getFormatedDate(new Date(), "yyyy-MM-dd HH:mm:ss"));
            profit.setDateTime(DateUtils.getFormatedDate(DateUtils.addDay(new Date(), -1), "yyyy-MM-dd HH:mm:ss"));
            profit.setUserId(userId.intValue());
            profit.setClientId(clientId);
            //profitDao.insert(profit);
            Profit profit1 = null;
            List<Profit> profits = profitDao.selectNewProfit(userId.intValue(), clientId, map.get(ft).getTradeAccount(), map.get(ft).getFundCode());
            if (!profits.isEmpty()) {
                profit1 = profits.get(0);
            }
            if (profit1 != null) {
                profit1.setAccumulateProfitValue(map.get(ft).getAccumIncome());
                profitDao.updateByPrimaryKeySelective(profit1);
            }
        }


        return null;

    }

    /**
     * 计算 总资产，总当日收益，最新净值日期，是否有在途
     *
     * @param funds
     * @param lookups
     * @param needT0
     * @return
     */
    @Override
    public AssetFundModel sumOfAsset(List<AssetFundModel> funds, List<Lookup> lookups,
                                     boolean needT0, Map<String, BigDecimal> fastRedeemShares, List<DividendModel> dividendModels,
                                     List<ConfirmModel> confirms,
                                     List<ApplyModel> applyModels, Long userId, String clientId, Set<String> fundCodes) {
        // 同个基金的汇总
        //Map<String, AssetFundModel> fundSums = new HashMap<>();
        // 最新的净值日期
        Date lastNetDate = null;
        // 基金代码
        String fundCode = null;


        List<AssetFundModel> fundSums = new ArrayList<>();
        // 计算总和
        for (AssetFundModel model : funds) {
            logger.debug("extractFunds 基金：{}，份额：{}", model.getFundCode(), model.getCurrentShares());

            // 是否是T0基金
            boolean isT0 = model.getAssetType() == GlobalConstant.ASSET_TYPE_WALLET;
            if (needT0 && !isT0) {
                continue;
            }

            if (!needT0 && isT0) {
                continue;
            }


            fundSums.add(model);

            // 设置最新净值日期
            Date netDate = model.getNetValueDate();
            if (lastNetDate == null) {
                lastNetDate = netDate;
            } else {
                // 如果比当前净值日期大，则用大的
                if (lastNetDate.before(netDate)) {
                    lastNetDate = netDate;
                }
            }
        }

        // 如果是T0, 先减掉快速赎回的份额
        // 计算总资产值和总日收益
        BigDecimal totalWorthValue = null;
        BigDecimal totalTodayIncome = null;
        BigDecimal totalShareIncome = null;
        BigDecimal totalAccumIncome = null;
        //累计收益 - add by Shangdu Lin - 20170531
        //BigDecimal totalAccumIncome=null;
        // 未付收益 - add by Shangdu Lin - 20170612
        BigDecimal totalUnpaidIncome = null;

        //基金编码集合
        //持有基金列表
        List<AssetFundModel> fundDetailList = new ArrayList<AssetFundModel>();
        for (AssetFundModel model : fundSums) {
            BigDecimal currentShares = model.getCurrentShares();
            BigDecimal enableShares = model.getEnableShares();
            // 如果当前工作日没有待确认的份额，则使用当前份额
            // 当前份额减掉快速赎回的份额
            String key = model.getFundCode() + model.getTradeAcco();
            if (fastRedeemShares != null && needT0 && fastRedeemShares.containsKey(key)) {

                currentShares = MoneyUtils.subtract(currentShares, fastRedeemShares.get(key));
            }

            // Shangdu Lin - 20170502
            // 4舍5入后再相加
            // why:因为在我的资产页，各个基金是分开显示的，而且每个基金都会显示资产，每个资产是4舍5入的，且基于此就算出总资产并显示
            // 资产=份额*净值
            BigDecimal worthValue = currentShares.multiply(model.getNetValue());
            worthValue = MoneyUtils.add(worthValue, model.getUnpaidIncome());
            worthValue = worthValue.setScale(2, BigDecimal.ROUND_HALF_UP);
            //设置每个基金的资产
            model.setTotalWorthValue(worthValue);
            totalWorthValue = MoneyUtils.add(totalWorthValue, worthValue);
            //计算持仓收益的现金分红部分

            /**
             *
             * 这里的分红收益总额
             *
             */
            BigDecimal totalDividend = new BigDecimal(0);
            for (DividendModel dividendModel : dividendModels) {
                if ("1".equals(dividendModel.getAutoBuy()) && model.getFundCode().equals(dividendModel.getFundCode()) && dividendModel.getTradeAccount().equals(model.getTradeAcco())) {
                    if (DateUtils.formatDate4(new Date()).compareTo(dividendModel.getEquityRegDate()) >= 0 && DateUtils.formatDate4(new Date()).compareTo(dividendModel.getDividendDate()) <= 0) {
                        model.setDividends("该基金最近有分红配送");
                    }
                    if (dividendModel.getDividendDate().compareTo(DateUtils.formatDate4(new Date())) < 0) {
                        totalDividend = MoneyUtils.add(totalDividend, dividendModel.getDividendBalance());
                    }
                }
            }
            if (model.getDividends() == null) {
                model.setDividends("");
            }

            BigDecimal accumIncome = null;
            if (needT0) {
                accumIncome = worthValue;
                for (ApplyModel applyModel : applyModels) {
                    if (applyModel.getFundCode().equals(model.getFundCode()) && applyModel.getTradeAcco().equals(model.getTradeAcco())) {
                        if (applyModel.getTAConfirmFlag().equals(GlobalConstant.TACONFIRM_FLAG_CONFIRMED)) {
                            if (applyModel.getFundBusinCode().equals(GlobalConstant.FUND_BUSIN_CODE_APPLY_BUY) || applyModel.getFundBusinCode().equals(GlobalConstant.FUND_BUSIN_CODE_APPLY_FIX_BUY)) {
                                accumIncome = MoneyUtils.subtract(accumIncome, applyModel.getBalance());
                            }
                            if (applyModel.getFundBusinCode().equals(GlobalConstant.FUND_BUSIN_CODE_APPLY_SELL) || applyModel.getFundBusinCode().equals(GlobalConstant.FUND_BUSIN_CODE_T0_FAST_APPLY_SELL)) {
                                //因为净值为1  所以可以直接拿份额算
                                accumIncome = MoneyUtils.add(accumIncome, applyModel.getShares());
                            }
                        }
                        if (applyModel.getTAConfirmFlag().equals(GlobalConstant.TACONFIRM_FLAG_REAL_SUCCESS) && applyModel.getFundBusinCode().equals(GlobalConstant.FUND_BUSIN_CODE_T0_FAST_APPLY_SELL)) {
                            accumIncome = MoneyUtils.add(accumIncome, applyModel.getShares());
                        }
                    }
                }
                for (ConfirmModel confirm : confirms) {
                    if (confirm.getFundCode().equals(model.getFundCode()) && confirm.getTradeAcco().equals(model.getTradeAcco())) {
                        if (confirm.getTAConfirmFlag().equals(GlobalConstant.TACONFIRM_FLAG_CONFIRMED)) {
                            if (confirm.getFundBusinCode().equals(GlobalConstant.FUND_BUSIN_CODE_FORCE_SELL)) {
                                accumIncome = MoneyUtils.add(accumIncome, confirm.getTradeConfirmBalance());
                            }
                        }
                    }
                }
            } else {
                accumIncome = MoneyUtils.add(worthValue, totalDividend);
                for (ConfirmModel confirm : confirms) {
                    if (confirm.getFundCode().equals(model.getFundCode()) && confirm.getTradeAcco().equals(model.getTradeAcco())) {
                        if (confirm.getTAConfirmFlag().equals(GlobalConstant.TACONFIRM_FLAG_CONFIRMED)) {
                            if (confirm.getFundBusinCode().equals(GlobalConstant.FUND_BUSIN_CODE_CONFIRM_BUY) || confirm.getFundBusinCode().equals(GlobalConstant.FUND_BUSIN_CODE_CONFIRM_FIX_BUY)) {
                                accumIncome = MoneyUtils.subtract(accumIncome, confirm.getTradeConfirmBalance());
                            }
                            if (confirm.getFundBusinCode().equals(GlobalConstant.FUND_BUSIN_CODE_CONFIRM_SELL)) {
                                accumIncome = MoneyUtils.add(accumIncome, confirm.getTradeConfirmBalance());
                            }
                        }
                    }
                }
            }

            model.setTotalAccumIncome(accumIncome);
            Profit profit = new Profit();
            profit.setAccumulateProfitValue(accumIncome);
            profit.setProfitValue(accumIncome);
            profit.setFundCode(model.getFundCode());
            profit.setTradeAcco(model.getTradeAcco());
            profit.setCreateTime(DateUtils.getFormatedDate(new Date(), "yyyy-MM-dd HH:mm:ss"));
            profit.setDateTime(DateUtils.getFormatedDate(DateUtils.addDay(new Date(), -1), "yyyy-MM-dd HH:mm:ss"));
            profit.setUserId(userId.intValue());
            profit.setClientId(clientId);
            //更新 累计收益
            Profit profit1 = null;
            List<Profit> profits = profitDao.selectNewProfit(userId.intValue(), clientId, model.getTradeAcco(), model.getFundCode());
            if (!profits.isEmpty()) {
                profit1 = profits.get(0);
            }
            if (profit1 != null) {
                profit1.setAccumulateProfitValue(accumIncome);
                profitDao.updateByPrimaryKeySelective(profit1);
            }
            //profitDao.insert(profit);
            totalAccumIncome = MoneyUtils.add(totalAccumIncome, accumIncome);

            fundDetailList.add(model);
        }


        if (needT0) {
            Map<String, AccumModel> map = new HashMap<>();
            for (ApplyModel applyModel : applyModels) {
                if (!applyModel.getTradeAcco().startsWith("ZH") && !fundCodes.contains(applyModel.getFundCode()) && CalculateAssetsUtils.isT0Fund(lookups, applyModel.getFundCode())) {
                    BigDecimal accumIncome = new BigDecimal(0);
                    if (applyModel.getTAConfirmFlag().equals(GlobalConstant.TACONFIRM_FLAG_CONFIRMED)) {
                        if (applyModel.getFundBusinCode().equals(GlobalConstant.FUND_BUSIN_CODE_APPLY_BUY) || applyModel.getFundBusinCode().equals(GlobalConstant.FUND_BUSIN_CODE_APPLY_FIX_BUY)) {
                            accumIncome = MoneyUtils.subtract(accumIncome, applyModel.getBalance());
                        }
                        if (applyModel.getFundBusinCode().equals(GlobalConstant.FUND_BUSIN_CODE_APPLY_SELL) || applyModel.getFundBusinCode().equals(GlobalConstant.FUND_BUSIN_CODE_T0_FAST_APPLY_SELL)) {
                            //因为净值为1  所以可以直接拿份额算
                            accumIncome = MoneyUtils.add(accumIncome, applyModel.getShares());
                        }
                    }
                    if (applyModel.getTAConfirmFlag().equals(GlobalConstant.TACONFIRM_FLAG_REAL_SUCCESS) && applyModel.getFundBusinCode().equals(GlobalConstant.FUND_BUSIN_CODE_T0_FAST_APPLY_SELL)) {
                        accumIncome = MoneyUtils.add(accumIncome, applyModel.getShares());
                    }
                    String key = applyModel.getFundCode() + applyModel.getTradeAcco();
                    AccumModel accumModel = AccumModel.builder().
                        accumIncome(accumIncome).
                        fundCode(applyModel.getFundCode()).
                        tradeAccount(applyModel.getTradeAcco()).
                        build();
                    if (map.containsKey(key)) {
                        map.put(key, map.get(key).setAccumIncome(MoneyUtils.add(map.get(key).getAccumIncome(), accumIncome)));
                    } else {
                        map.put(key, accumModel);
                    }

                }
            }
            for (ConfirmModel confirm : confirms) {
                if (!confirm.getTradeAcco().startsWith("ZH") && !fundCodes.contains(confirm.getFundCode()) && CalculateAssetsUtils.isT0Fund(lookups, confirm.getFundCode())) {
                    if (confirm.getTAConfirmFlag().equals(GlobalConstant.TACONFIRM_FLAG_CONFIRMED)) {
                        if (confirm.getFundBusinCode().equals(GlobalConstant.FUND_BUSIN_CODE_FORCE_SELL)) {
                            String key = confirm.getFundCode() + confirm.getTradeAcco();
                            AccumModel accumModel = AccumModel.builder().
                                accumIncome(confirm.getTradeConfirmBalance()).
                                fundCode(confirm.getFundCode()).
                                tradeAccount(confirm.getTradeAcco()).
                                build();
                            if (map.containsKey(key)) {
                                map.put(key, map.get(key).setAccumIncome(MoneyUtils.add(map.get(key).getAccumIncome(), confirm.getTradeConfirmBalance())));
                            } else {
                                map.put(key, accumModel);
                            }
                        }
                    }
                }
            }
            for (String ft : map.keySet()) {
                Profit profit = new Profit();
                profit.setAccumulateProfitValue(map.get(ft).getAccumIncome());
                profit.setProfitValue(map.get(ft).getAccumIncome());
                profit.setFundCode(map.get(ft).getFundCode());
                profit.setTradeAcco(map.get(ft).getTradeAccount());
                profit.setCreateTime(DateUtils.getFormatedDate(new Date(), "yyyy-MM-dd HH:mm:ss"));
                profit.setDateTime(DateUtils.getFormatedDate(DateUtils.addDay(new Date(), -1), "yyyy-MM-dd HH:mm:ss"));
                profit.setUserId(userId.intValue());
                profit.setClientId(clientId);
                //profitDao.insert(profit);
                Profit profit1 = null;
                List<Profit> profits = profitDao.selectNewProfit(userId.intValue(), clientId, map.get(ft).getTradeAccount(), map.get(ft).getFundCode());
                if (!profits.isEmpty()) {
                    profit1 = profits.get(0);
                }
                if (profit1 != null) {
                    profit1.setAccumulateProfitValue(map.get(ft).getAccumIncome());
                    profitDao.updateByPrimaryKeySelective(profit1);
                }
            }

        } else {
            Map<String, AccumModel> map = new HashMap<>();
            for (ConfirmModel confirm : confirms) {
                if (!confirm.getTradeAcco().startsWith("ZH") && !fundCodes.contains(confirm.getFundCode())) {
                    BigDecimal accumIncome = new BigDecimal(0);
                    if (!CalculateAssetsUtils.isT0Fund(lookups, confirm.getFundCode())) {
                        if (confirm.getTAConfirmFlag().equals(GlobalConstant.TACONFIRM_FLAG_CONFIRMED)) {
                            if (confirm.getFundBusinCode().equals(GlobalConstant.FUND_BUSIN_CODE_CONFIRM_BUY) || confirm.getFundBusinCode().equals(GlobalConstant.FUND_BUSIN_CODE_CONFIRM_FIX_BUY)) {
                                accumIncome = MoneyUtils.subtract(accumIncome, confirm.getTradeConfirmBalance());
                                logger.debug("业务编码：{}，时间：{}，收益：{}", confirm.getFundBusinCode(), confirm.getAffirmDate(), confirm.getTradeConfirmBalance());
                            }
                            if (confirm.getFundBusinCode().equals(GlobalConstant.FUND_BUSIN_CODE_CONFIRM_SELL)) {
                                accumIncome = MoneyUtils.add(accumIncome, confirm.getTradeConfirmBalance());
                                logger.debug("业务编码：{}，时间：{}，收益：{}", confirm.getFundBusinCode(), confirm.getAffirmDate(), confirm.getTradeConfirmBalance());
                            }
                        }
                    }
                    String key = confirm.getFundCode() + confirm.getTradeAcco();
                    AccumModel accumModel = AccumModel.builder().
                        accumIncome(accumIncome).
                        fundCode(confirm.getFundCode()).
                        tradeAccount(confirm.getTradeAcco()).
                        build();
                    if (map.containsKey(key)) {
                        map.put(key, map.get(key).setAccumIncome(MoneyUtils.add(map.get(key).getAccumIncome(), accumIncome)));
                    } else {
                        map.put(key, accumModel);
                    }
                }
            }
            //瑞富宝没有现金分红
            BigDecimal totalDividend = new BigDecimal(0);
            for (DividendModel dividendModel : dividendModels) {
                //现金分红
                if ("1".equals(dividendModel.getAutoBuy())
                    // 没有持仓（全赎）
                    && !fundCodes.contains(dividendModel.getFundCode())
                    // 普通基金
                    && !CalculateAssetsUtils.isT0Fund(lookups, dividendModel.getFundCode())
                    // 分红日在今天之前
                    && dividendModel.getDividendDate().compareTo(DateUtils.formatDate4(new Date())) < 0) {
                    String key = dividendModel.getFundCode() + dividendModel.getTradeAccount();
                    AccumModel accumModel = AccumModel.builder().
                        accumIncome(dividendModel.getDividendBalance()).
                        fundCode(dividendModel.getFundCode()).
                        tradeAccount(dividendModel.getTradeAccount()).
                        build();
                    if (map.containsKey(key)) {
                        map.put(key, map.get(key).setAccumIncome(MoneyUtils.add(map.get(key).getAccumIncome(), dividendModel.getDividendBalance())));
                    } else {
                        map.put(key, accumModel);
                    }
                }
            }
            for (String ft : map.keySet()) {
                Profit profit = new Profit();
                profit.setAccumulateProfitValue(map.get(ft).getAccumIncome());
                profit.setProfitValue(map.get(ft).getAccumIncome());
                profit.setTradeAcco(map.get(ft).getTradeAccount());
                profit.setFundCode(map.get(ft).getFundCode());
                profit.setCreateTime(DateUtils.getFormatedDate(new Date(), "yyyy-MM-dd HH:mm:ss"));
                profit.setDateTime(DateUtils.getFormatedDate(DateUtils.addDay(new Date(), -1), "yyyy-MM-dd HH:mm:ss"));
                profit.setUserId(userId.intValue());
                profit.setClientId(clientId);
                //profitDao.insert(profit);
                Profit profit1 = null;
                List<Profit> profits = profitDao.selectNewProfit(userId.intValue(), clientId, map.get(ft).getTradeAccount(), map.get(ft).getFundCode());
                if (!profits.isEmpty()) {
                    profit1 = profits.get(0);
                }
                if (profit1 != null) {
                    profit1.setAccumulateProfitValue(map.get(ft).getAccumIncome());
                    profitDao.updateByPrimaryKeySelective(profit1);
                }
            }
        }


        //logger.warn("零钱包总在途金额:{},零钱包总资产:{}", fund.getInTransitAmount(), fund.getTotalWorthValue());
        return null;
    }


    /**
     * 计算每笔持仓的份额，当日收益，净值日期， 日收益
     *
     * @param shares
     * @param lookups
     * @param fundNetValueList
     * @return
     */
    @Override
    public List<AssetFundModel> extractFunds(List<ShareModel> shares, List<Lookup> lookups,
                                             List<FundNetValueResult> fundNetValueList, Set<String> fundCodes) {
        List<AssetFundModel> funds = new ArrayList<>();
        Map<String, FundNetValueResult> map = new HashMap<>();
        // 计算份额，当日收益，净值日期， 日收益
        for (ShareModel share : shares) {
            if (share.getFundCode().equals("161728")) {
                continue;
            }
            fundCodes.add(share.getFundCode());
            // 如果当前份额为0，则不考虑在内
            BigDecimal currentShare = share.getCurrentShare();

            // 从聚源获取基金基础信息
            String fundCode = share.getFundCode();
            FundNetValueResult netValueResult = new FundNetValueResult();


            AssetFundModel assetFundModel = new AssetFundModel();
            netValueResult = CalculateAssetsUtils.setNetValue(fundCode, netValueResult, fundNetValueList);
            //交易账号
            assetFundModel.setTradeAcco(share.getTradeAccount());
            //可用份额
            assetFundModel.setEnableShares(share.getEnableShares());
            // 基金代码
            assetFundModel.setFundCode(share.getFundCode());
            // 当前份额
            assetFundModel.setCurrentShares(currentShare);
            logger.debug("extractFunds 基金：{}，份额：{}", assetFundModel.getFundCode(), assetFundModel.getCurrentShares());
            // 单位净值
            assetFundModel.setNetValue(netValueResult.getUnitNV());
            // 单位净值日期
            assetFundModel.setNetValueDate(netValueResult.getTradingDay());
            logger.debug("净值日期：{}，基金：{}", netValueResult.getTradingDay(), netValueResult.getFundCode());
            // 资产类型
            assetFundModel.setAssetType(GlobalConstant.ASSET_TYPE_FUND);
            // 累计收益
            assetFundModel.setAccumIncome(share.getAccumIncome());
            // 累计收益 = 每月5号06文件中的“红利资金” + 每日05文件中的“货币基金未分配收益金额”
            assetFundModel.setUnpaidIncome(share.getUnpaidIncome());
            //成本
            assetFundModel.setCost(share.getCost());
            CalculateAssetsUtils.setIncome(netValueResult, fundCode, assetFundModel, lookups);
            //logger.warn("share未付收益：{}", share.getUnpaidIncome());


            funds.add(assetFundModel);
        }

        return funds;
    }

    @Override
    public void getInsidePortfolio(User user, Boolean flag) {
        Map<String, Object> map = new HashMap<>();
        List<Map<String, Object>> list = new ArrayList<>();
        PortfolioApplyListResult result = new PortfolioApplyListResult();
        map = tradeConfirmQueryService.query(GlobalConstant.MAX_REQUEST_NUM, 1, 1, "1", "", user.getExternalClientId(), "", "", "", "", "", "", "", "", "", "", "", "", "", "");
        // 查询结果
        list = new ArrayList<>();
        HundsunUtils.ConvertToList(map, list, result);

        // populate
        List<ConfirmModel> confirms = ModelPopulateUtils.populateConfirm(list);
        map = tradeApplyQueryService.query(GlobalConstant.MAX_REQUEST_NUM, 1, 1, "1", "", user.getExternalClientId(), "", "", "", "", "", "", "", "", "", "", "", "");
        // 查询结果
        list = new ArrayList<>();
        HundsunUtils.ConvertToList(map, list, result);

        // 交易业务名称
        List<Lookup> tradeLookups = lookupDao.getLookupByType(RuleConstant.RULE_LOOKUP_TYPE_BUSINAME);
        // 银行名称
        List<Lookup> bankLookups = lookupDao.getLookupByType(RuleConstant.RULE_LOOKUP_TYPE_HSBANK);
        // populate
        List<PortfolioApplyModel> applys = ModelPopulateUtils.populatePortfolioApply(list, result, tradeLookups, bankLookups, user.getIsOrg());

        Map<String, ConfirmModel> modelMap = new HashMap<>();
        //组合投资查询
        PortfolioQryDto portfolioQryDto = PortfolioQryDto.builder()
            .request_num(GlobalConstant.MAX_REQUEST_NUM)
            .reqry_recordsum_flag("1")
            .sort_direction("1")
            .client_id(user.getExternalClientId())
            .qry_beginrownum("1")
            .build();

        map = portfolioQryService.query(portfolioQryDto);
        list = new ArrayList<>();
        HundsunUtils.ConvertToList(map, list, result);

        //将同一组合的基金放在一起  存入一个map
        List<PortfolioQryModel> portfolioQryModels = ModelPopulateUtils.populatePortfolioQry(list);
        for (ConfirmModel confirmModel : confirms) {
            if (StringUtils.isNotBlank(confirmModel.getPortfolioCode())) {

                if (modelMap.containsKey(confirmModel.getPortfolioAllotNo())) {
                    modelMap.get(confirmModel.getPortfolioAllotNo()).setConfirmBalance(MoneyUtils.add(modelMap.get(confirmModel.getPortfolioAllotNo()).getConfirmBalance(), confirmModel.getConfirmBalance()));
                    modelMap.get(confirmModel.getPortfolioAllotNo()).setConfirmShares(MoneyUtils.add(modelMap.get(confirmModel.getPortfolioAllotNo()).getConfirmShares(), confirmModel.getConfirmShares()));
                } else {
                    // 设置交易业务名称
                    if (tradeLookups != null) {
                        for (Lookup lookup : tradeLookups) {
                            if (lookup.getComponentValue().equals(confirmModel.getFundBusinCode())) {
                                confirmModel.setFundBusinName(lookup.getRuleText());
                                break;
                            }
                        }
                    }
                    //不同的业务  从不同的地方 获取组合名称  恒生就是 这么奇怪
                    if (GlobalConstant.FUND_BUSIN_CODE_CONFIRM_BUY.equals(confirmModel.getFundBusinCode())) {
                        for (ApplyModel applyModel : applys) {
                            if (applyModel.getPortfolioAllotNo().equals(confirmModel.getPortfolioAllotNo())) {
                                confirmModel.setPortfolioName(applyModel.getProtocolName());
                                break;
                            }
                        }
                    } else {
                        for (PortfolioQryModel portfolioQryModel : portfolioQryModels) {
                            if (confirmModel.getPortfolioCode().equals(portfolioQryModel.getPortfolioCode())) {
                                confirmModel.setPortfolioName(portfolioQryModel.getProtocolName());
                                break;
                            }
                        }
                    }

                    modelMap.put(confirmModel.getPortfolioAllotNo(), confirmModel);
                }

            }
        }

        for (String portfolioAllotNo : modelMap.keySet()) {
            ConfirmModel confirmModel = modelMap.get(portfolioAllotNo);
            InsidePortfolio insidePortfolio;
            if (flag) {
                insidePortfolio = InsidePortfolio.builder()
                    .applyDate(DateUtils.stringToDate(confirmModel.getOrderDate(), GlobalConstant.DATE_FORMAT_YYYYMMDD))
                    .balance(confirmModel.getConfirmBalance())
                    .businessType(confirmModel.getFundBusinName())
                    .portfolioName(confirmModel.getPortfolioCode())
                    .share(confirmModel.getConfirmShares())
                    .userMobile(user.getUserMobile())
                    .userName(user.getUserName())
                    .build();
            } else {
                insidePortfolio = InsidePortfolio.builder()
                    .applyDate(DateUtils.stringToDate(confirmModel.getOrderDate(), GlobalConstant.DATE_FORMAT_YYYYMMDD))
                    .balance(confirmModel.getConfirmBalance())
                    .businessType(confirmModel.getFundBusinName())
                    .portfolioName(confirmModel.getPortfolioName())
                    .share(confirmModel.getConfirmShares())
                    .userMobile(user.getUserMobile())
                    .userName(user.getUserName())
                    .build();
            }
            insidePortfolioDao.insert(insidePortfolio);
        }
    }

    @Override
    public void getPortfolioTradeAccount(User user) {
        Map<String, Object> map = new HashMap<>();
        List<Map<String, Object>> list = new ArrayList<>();
        PortfolioApplyListResult result = new PortfolioApplyListResult();
        map = tradeApplyQueryService.query(GlobalConstant.MAX_REQUEST_NUM, 1, 1, "1", "", user.getExternalClientId(), "", "", "", "", "", "", "", "", "", "", "", "");
        // 查询结果
        list = new ArrayList<>();
        HundsunUtils.ConvertToList(map, list, result);

        // 交易业务名称
        List<Lookup> tradeLookups = lookupDao.getLookupByType(RuleConstant.RULE_LOOKUP_TYPE_BUSINAME);
        // 银行名称
        List<Lookup> bankLookups = lookupDao.getLookupByType(RuleConstant.RULE_LOOKUP_TYPE_HSBANK);
        // populate
        List<PortfolioApplyModel> applys = ModelPopulateUtils.populatePortfolioApply(list, result, tradeLookups, bankLookups, user.getIsOrg());

        for (PortfolioApplyModel applyModel : applys) {
            if (StringUtils.isBlank(applyModel.getPortfolioCode())) {
                continue;
            }
            PortfolioTradeAcco portfolioTradeAcco = new PortfolioTradeAcco();
            portfolioTradeAcco.setPortfolioTradeAcco(applyModel.getTradeAcco());
            List<PortfolioTradeAcco> portfolioTradeAccoList = portfolioTradeAccoDao.selectByPortfolioTradeAccount(portfolioTradeAcco);
            if (portfolioTradeAccoList == null || portfolioTradeAccoList.size() == 0) {
                portfolioTradeAcco.setPortfolioAllotNo(applyModel.getPortfolioAllotNo());
                UserBank userBank = userBankDao.getEntityByBankNo(user.getUserId(), applyModel.getReceivableAccount(), GlobalConstant.CAPTIAL_MODE_I);
                if (userBank == null) {
                    userBank = userBankDao.getEntityByBankNo(user.getUserId(), applyModel.getReceivableAccount(), GlobalConstant.CAPITAL_MODE_COUNTER);
                }
                if (userBank != null) {
                    portfolioTradeAcco.setTradeAcco(userBank.getExternalTradeAccount());
                }
                portfolioTradeAcco.setPortfolioTradeAcco(applyModel.getTradeAcco());
                portfolioTradeAcco.setUserId(user.getUserId().intValue());
                portfolioTradeAcco.setPortfolioCode(applyModel.getExtPortfolioCode());
                portfolioTradeAccoDao.insert(portfolioTradeAcco);
            }
        }
    }

    @Override
    public void getPortfolioAssets(User user) {
        Map<String, Object> map = new HashMap<>();
        List<Map<String, Object>> list = new ArrayList<>();
        CombSharesQryDto combSharesQryDto = CombSharesQryDto.builder()
            .request_num(GlobalConstant.MAX_REQUEST_NUM)
            .reqry_recordsum_flag("1")
            .client_id(user.getExternalClientId())
            .qry_beginrownum("1")
            .build();
        map = hsCombSharesQryService.query(combSharesQryDto);
        BaseResult result = new BaseResult();
        list = new ArrayList<>();
        HundsunUtils.ConvertToList(map, list, result);
        List<CombSharesQryModel> combSharesQryModels = ModelPopulateUtils.populateCombSharesQry(list);
        if (combSharesQryModels.isEmpty()) {
            return;
        }

        List<String> fundCodeList = new ArrayList<String>();
        for (CombSharesQryModel combSharesQryModel : combSharesQryModels) {
            fundCodeList.add(combSharesQryModel.getFundCode());
        }

        if (fundCodeList.isEmpty()) {
            return;
        }

        List<FundNetValueResult> fundNetValueList = null;
        boolean gliDataException = false;
        try {
            fundNetValueList = fundDetailService.getFundNetValueByBatch(fundCodeList, DateUtils.addDay(new Date(), -1));
        } catch (Exception ex) {
            ExceptionUtil.logError(logger, "queryAssets - fundDetailService - Exception:", ex);
            gliDataException = true;
        }
        Map<String, CombSharesQryModel> modelMap = new HashMap<>();
        for (CombSharesQryModel combSharesQryModel : combSharesQryModels) {
            for (FundNetValueResult fundNetValueResult : fundNetValueList) {
                if (fundNetValueResult == null) {
                    continue;
                }
                if (fundNetValueResult.getFundCode().equals(combSharesQryModel.getFundCode())) {
                    combSharesQryModel.setWorthValue(combSharesQryModel.getFundShare().multiply(fundNetValueResult.getUnitNV()));
                    break;
                }
            }
            if (modelMap.containsKey(combSharesQryModel.getPortfolioCode())) {
                modelMap.get(combSharesQryModel.getPortfolioCode()).setWorthValue(MoneyUtils.add(modelMap.get(combSharesQryModel.getPortfolioCode()).getWorthValue(), combSharesQryModel.getWorthValue()));
                modelMap.get(combSharesQryModel.getPortfolioCode()).setFundShare(MoneyUtils.add(modelMap.get(combSharesQryModel.getPortfolioCode()).getFundShare(), combSharesQryModel.getFundShare()));
            } else {
                modelMap.put(combSharesQryModel.getPortfolioCode(), combSharesQryModel);
            }
        }

        for (String portfolioCode : modelMap.keySet()) {
            if ("2001".equals(portfolioCode)) {
                continue;
            }
            FundCombination fundCombination = fundCombinationDao.queryByCombinationCode(portfolioCode);
            CombSharesQryModel combSharesQryModel = modelMap.get(portfolioCode);
            InsidePortfolioAssets insidePortfolioAssets = InsidePortfolioAssets.builder()
                .portfolioName(fundCombination.getCombinationName())
                .share(combSharesQryModel.getFundShare())
                .userMobile(user.getUserMobile())
                .userName(user.getUserName())
                .worth(combSharesQryModel.getWorthValue())
                .build();
            insidePortfolioAssetsDao.insert(insidePortfolioAssets);
        }


    }


    @Override
    public List<InsidePortfolio> getMobile() {
        return insidePortfolioDao.selectMobile();
    }

    @Override
    public void dividendTest(User user, int i) {
        HsDividendQryDto hsDividendQryDto = new HsDividendQryDto();
        hsDividendQryDto.setClient_id(user.getExternalClientId());
        hsDividendQryDto.setConfirmdate_begin(DateUtil.format(DateUtils.addDay(new Date(), i), "yyyyMMdd"));
        hsDividendQryDto.setReqry_recordsum_flag("1");
        hsDividendQryDto.setRequest_num(50);
        hsDividendQryDto.setQry_beginrownum(1);
        //获取分红明细
        List<HsFundDividendQryResponse> fundDividendQryResponses = dividendsQueryService.query(hsDividendQryDto);
    }
}
